Parallel thread safety (fun fun)

TheFlyingFiddle theflyingfiddle at gmail.com
Sat Feb 1 11:26:01 PST 2014


On Friday, 31 January 2014 at 21:33:50 UTC, Mineko wrote:
> So, I'm implementing some parallelism in my engine (maybe some 
> concurrency where appropriate later), and I'm having some 
> issues with thread safety, and synchronize ain't cutting it.
>
> What I figure is that if I can get the IO class working within 
> a parallel thread then everything else should fall in place, 
> so, I need some help making the IO class thread-safe. (I'm new 
> to thread safety btw, like, yesterday new >_>)
>
> Relevent file here: 
> https://github.com/MinekoRox/Breaker-Engine/blob/master/src/breaker/utility/io.d
>
> Feel free to drop any other suggestions on what to do with that 
> class if you want, always appreciated. :)

First of all you are using the synchronized statement incorrecly.

synchronized bool addTime; <-- This does absolutely nothing.

I am supprised this code is allowed.

You can only use synchronized on class methods 
http://dlang.org/class.html#synchronized-functions or on an 
abitrary
block of code 
http://dlang.org/statement.html#SynchronizedStatement

If you want to synchronize access to data you will have to either 
make them shared and use  synchronized/atomic operations on them 
or synchronize the use yourself. This is a quite complex and 
bugprone activity and if your just getting started i would not 
reccomend it. There is a simpler / better way that i will 
describe later.

Secondly the only use of concurency that i see in the IO class is 
the attempt to write to a file from multiple threads. In the 
write() method. This is not a good idea. Firstly you will not be 
able to write any faster to the file since it's IO bound in any 
case. The only effect if any is that you will use more resources 
and that the output will appear in the file in random order. 
(Probably not what you want)


I would reccomend using message passing instead of even 
attempting to synchronize things. This is ALOT simpler and if 
your goal is to offload IO to another thread it's the way to go 
IMHO.

Here is a very simple logging application that writes to a file 
using std.concurrency through message passing. To make things 
simple it can only log messages from the thread that started it. 
This would probably be the main thread in a game.

module main;
import logger;

void main()
{
     startLoggerThread("log.txt");

     log("Hello");
     log("World");

     stopLoggerThread();
}

//logger.d
module logger;

import std.concurrency;
import std.file;

//This is a unique identifier for a thread.
Tid loggerTid;

//Starts the logger thread.
//(This must be done before any logging can take place.)
void startLoggerThread(string logFile)
{
     loggerTid = spawn(&loggerEntry, logFile);
}

//Stops the logger thread.
void stopLoggerThread()
{
     send(loggerTid, Shutdown());
}

//Called by the thread that started the logger.
void log(string msg)
{
     //Send the message to log to the logger thread
     //identified by the loggerTid.
     send(loggerTid, msg);
}

//A tag struct symbolising the message shutdown.
struct Shutdown { }

void loggerEntry(string logFile)
{
     bool running = true;
     //Recevie logging requests until stopLoggerThread is called.
     while(running)
     {
     	receive(
     	   //We get a message here when log is called.
     	   (string msg)
     	   {
                //Create file if it does not already exists
     	       //otherwise append to it.
     	       if(!exists(logFile))
     	           write(logFile, msg ~ "\n");
     	       else
     		   append(logFile, msg ~ "\n");
     	    },
     	    //If we get this message we stop the logger thread.
     	    (Shutdown _)
     	    {
                running = false;
     	    });
     }
}

The example works by first creating a logging thread. This thread 
then listens to logging requests from the main thread. And logs 
all messages it receives.

I would reccomend reading the TDPL chapter on concurrency if you 
want to learn more.

//Hope this was all helpful








More information about the Digitalmars-d-learn mailing list