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