| TIP: Click on subject to list as thread! | ANSI |
| echo: | |
|---|---|
| to: | |
| from: | |
| date: | |
| subject: | C++ / threads |
RC> Do you know of any book/publication that will explain the concepts of
RC> threads and programming in a multithreaded environment.
RC> I don't fully understand the concepts, and would like to see if it would
RC> be useful in future projects.
I haven't bought books that talk about these subjects at an introductory
level in quite some time, so I'm not sure what to recommend to you.
Threads are actually fairly simple conceptually, but can be difficult to
use in real programs because of timing and data consistency concerns.
Basically, a thread is a path of execution through a program. You could
also say it is a set of resources including a program counter, registers, a
stack, and a thread control block managed by the operating system.
One way to look at the difference between a process and a thread is that
processes don't execute anything, they simply own resources such as address
space, memory, file handles, and process control blocks. Threads are the
entities that actually run code. They live inside a process, using its
resources. On older operating systems, one process could only have one
thread, so the idea of processes and threads was intertwined in a very
specific way. With OS/2 and other modern operating systems, a single
process can have multiple threads. What this means is that you can write
your programs to do more than one thing at a time without having to mess
around with complicated event switching systems.
For instance, if you want to write a very fast file copy program, you may
decide to structure it so that it uses two threads. One thread will be the
source file reader thread, the other thread will write to the destination
file. Obviously you need some way to pass the data that has been read from
the reader thread to the write thread. This mechanism also must be able to
handle some differences in the read and write performance. You could use a
simple queue of memory blocks set up to be used as disk I/O buffers. So
your program structure would look something like this:
source => reader => queue of disk => writer => destination
file thread I/O buffers thread file
Now this may look much like a "normal" single threaded program,
but the key difference is that you set up one thread for reading and
another for writing. The algorithms for each thread would be roughly like
this:
reader thread:
while( there's more unread data )
{
read a block of data from the disk into a buffer
place the filled buffer into a FIFO queue
}
signal writer thread that there is no more data
end thread
writer thread:
while( ( reader thread hasn't finished )
or ( there's more data in the queue ) )
{
get a buffer from the queue (wait if necessary)
write the buffer to the destination file
}
end thread
Now if you are reading from one disk and writing to another, this program
will be a lot faster than if it was written using a single thread. The
reason is that the read and write threads are I/O intensive and OS/2 can
overlap CPU and multiple I/O operations. So when the reader thread requests
a disk read, OS/2 will go start the operation and then go back to running
the program. If there's data already read into memory, the program will
then start a write operation via the writer thread. OS/2 starts that
operation and then goes back to running the program. In the meantime, the
read operation may have finished and more data is available to initiate
another write operation. Thus reads and writes are being overlapped, thus
greatly increasing overall throughput over what you would get if reads and
writes were not overlapped. Graphically, this overlapping might look like
this:
----------------------------- timeline ---------------------->
0 1 2 3 4 5 6 7 8
=read=> =read=> =read=>
=write=> =write=> =write=>
Now if the same work was done in a single threaded system, it would look like this:
=read=> =write=> =read=> =write=> =read=> =write=>
So you can see that the dual-thread approach in this comparison takes less
than 5 time units to complete whereas the single-thread approach takes over
7 time units.
While this probably seems pretty simple, you have to remember to use
semaphores to control timing so that the writer thread doesn't start
writing out data until there is a full buffer to use and the reader thread
doesn't start reusing a buffer that the
writer thread hasn't finished writing out.
Well, hopefully the above discussion was useful to you or somebody else.
It's a bit oversimplified, but shows the basic ideas involved.
--- Maximus/2 2.01wb
* Origin: OS/2 Connection {at} Mira Mesa, CA (1:202/354)SEEN-BY: 12/2442 54/54 620/243 624/50 632/348 640/820 690/660 711/409 410 413 SEEN-BY: 711/430 807 808 809 934 712/353 623 713/888 800/1 @PATH: 202/354 301 1 3615/50 229/2 12/2442 711/409 54/54 711/808 809 934 |
|
| SOURCE: echomail via fidonet.ozzmosis.com | |
Email questions or comments to sysop@ipingthereforeiam.com
All parts of this website painstakingly hand-crafted in the U.S.A.!
IPTIA BBS/MUD/Terminal/Game Server List, © 2025 IPTIA Consulting™.