Multithreaded file IO?

Jonathan M Davis jmdavisProg at gmx.com
Fri Sep 23 22:24:00 PDT 2011


On Saturday, September 24, 2011 01:05:52 Jerry Quinn wrote:
> Jonathan M Davis Wrote:
> > On Friday, September 23, 2011 23:01:17 Jerry Quinn wrote:
> > 
> > A direct rewrite would involve using shared and synchronized (either on
> > the class or a synchronized block around the code that you want to
> > lock). However, the more idiomatic way to do it would be to use
> > std.concurrency and have the threads pass messages to each other using
> > send and receive.
> 
> I'm trying the direct rewrite but having problems with shared and
> synchronized.
> 
> class queue {
>   File file;
>   this(string infile) {
>     file.open(infile);
>   }
>   synchronized void put(string s) {
>     file.writeln(s);
>   }
> }
> 
> queue.d(10): Error: template std.stdio.File.writeln(S...) does not match any
> function template declaration queue.d(10): Error: template
> std.stdio.File.writeln(S...) cannot deduce template function from argument
> types !()(string)
> 
> Remove the synchronized and it compiles fine with 2.055.

Technically, sychronized should go on the _class_ and not the function, but 
I'm not sure if dmd is currently correctly implemented in that respect (since 
if it is, it should actually be an error to stick synchronized on a function). 
Regardless of that, however, unless you use shared (I don't know if you are), 
each instance of queue is going to be on its own thread. So, no mutexes will 
be necessary, but you won't be able to have multiple threads writing to the 
same File. It could get messy.

You could use a synchronized block instead of synchronizing the class

void put(string s)
{
    synchronized(this)
    {
        file.writeln(s);
    }
}

and see if that works. But you still need the variable to be shared.

> > So, what you'd probably do is spawn 3 threads from the main thread. One
> > would read the file and send the data to another thread. That second
> > thread would process the data, then it would send it to the third
> > thread, which would write it to disk.
> 
> I think that would become messy when you have multiple processing threads. 
> The reader and writer would have to handshake with all the processors.

The reader therad would be free to read at whatever rate that it can. And the 
processing thread would be free to process at whatever rate that it can. The 
writer thread would be free to write and whatever rate it can. I/O issues 
would be reduced (especially if the files be read and written to are on 
separate drives), since the reading and writing threads would be separate. I 
don't see why it would be particularly messy. It's essentially what TDPL 
suggests a file copy function should do except that there's a thread in the 
middle which does so processing of the data before sending it the thread doing 
the writing. Really, this is a classic example of the sort of situation which 
std.concurrency's message passing is intended for.

> > Unfortunately, I'm not aware of any good code examples of this sort of
> > thing online. TDPL has some good examples, but obviously you'd have to
> > have the book to read it. Given some time, I could probably cook up an
> > example, but I don't have anything on hand.
> 
> std.parallelism actually looks the closest to what I want.  Not sure if I
> can make it work easily though.

For std.parallelism to work, each iteration of a parallel foreach _must_ be 
_completely_ separate from the others. They can't access the same data. So, 
for instance, they could access separate elements in an array, but they can't 
ever access the same element (unless none of the write to it), and something 
like a file is not going to work at all, since then you'd be trying to write to 
the file from multiple threads at once with no synchronization whatsoever. 
std.parallelism is for when you do the same thing many times _in parallel_ 
with each other, and your use case does not sound like that at all. I really 
think that std.concurrency is what you should be using if you don't want to do 
it the C/C++ way and use shared.

- Jonathan M Davis


More information about the Digitalmars-d-learn mailing list