Parallel thread safety (fun fun)

Mineko uminekorox at gmail.com
Sat Feb 1 11:55:50 PST 2014


On Saturday, 1 February 2014 at 19:26:03 UTC, TheFlyingFiddle 
wrote:
> 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

Yes it was, this was more or less what I was looking for, 
especially about the synchronization part, thank you.


More information about the Digitalmars-d-learn mailing list