CachedBandBlocksManager.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2008 National Institute For Space Research (INPE) - Brazil.
2 
3  This file is part of the TerraLib - a Framework for building GIS enabled applications.
4 
5  TerraLib is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  TerraLib is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with TerraLib. See COPYING. If not, write to
17  TerraLib Team at <terralib-team@terralib.org>.
18  */
19 
20 /*!
21  \file terralib/memory/CachedBandBlocksManager.cpp
22 
23  \brief RAM cached and tiled raster band blocks manager.
24 */
25 
26 // TerraLib
27 #include "../common/PlatformUtils.h"
28 #include "../raster/Band.h"
29 #include "../raster/BandProperty.h"
31 
32 // STL
33 #include <algorithm>
34 
36 {
37  m_rasterPtr = nullptr;
44  m_getBlockPointer_BlkPtr = nullptr;
45 }
46 
48 {
49  initState();
50 }
51 
53 {
54  free();
55 }
56 
58  const te::rst::Raster& externalRaster, const unsigned char maxMemPercentUsed,
59  const unsigned int dataPrefetchThreshold)
60 {
61  free();
62 
63  // Finding the global block dimensions
64 
65  unsigned int maxBlockSizeBytes = 0;
66 
67  for( unsigned int bandIdx = 0 ; bandIdx < externalRaster.getNumberOfBands() ;
68  ++bandIdx )
69  {
70  if( maxBlockSizeBytes < (unsigned int)externalRaster.getBand( bandIdx )->getBlockSize() )
71  maxBlockSizeBytes = (unsigned int)externalRaster.getBand( bandIdx )->getBlockSize();
72  }
73 
74  const double totalPhysMem = (double)te::common::GetTotalPhysicalMemory();
75  const double usedVMem = (double)te::common::GetUsedVirtualMemory();
76  const double totalVMem = ( (double)te::common::GetTotalVirtualMemory() );
77  const double freeVMem = ( ((double)maxMemPercentUsed) / 100.0 ) *
78  std::min( totalPhysMem, ( totalVMem - usedVMem ) );
79  const unsigned int maxNumberOfCacheBlocks = (unsigned int)
80  std::max( 1.0, std::ceil( freeVMem / ((double)maxBlockSizeBytes) ) );
81 
82  return initialize( maxNumberOfCacheBlocks, externalRaster, dataPrefetchThreshold );
83 }
84 
86  const unsigned int maxNumberOfCacheBlocks,
87  const te::rst::Raster& externalRaster,
88  const unsigned int dataPrefetchThreshold)
89 {
90  free();
91 
92  // Finding the global block dimensions
93 
94  unsigned int numberOfRasterBlocks = 0;
95 
96  for( unsigned int bandIdx = 0 ; bandIdx < externalRaster.getNumberOfBands() ;
97  ++bandIdx )
98  {
99  if( m_globalBlocksNumberX < (unsigned int)externalRaster.getBand( bandIdx )->getProperty()->m_nblocksx )
100  m_globalBlocksNumberX = (unsigned int)externalRaster.getBand( bandIdx )->getProperty()->m_nblocksx;
101 
102  if( m_globalBlocksNumberY < (unsigned int)externalRaster.getBand( bandIdx )->getProperty()->m_nblocksy )
103  m_globalBlocksNumberY = (unsigned int)externalRaster.getBand( bandIdx )->getProperty()->m_nblocksy;
104 
105  if( m_globalBlockSizeBytes < (unsigned int)externalRaster.getBand( bandIdx )->getBlockSize() )
106  m_globalBlockSizeBytes = (unsigned int)externalRaster.getBand( bandIdx )->getBlockSize();
107 
108  numberOfRasterBlocks +=
109  ( externalRaster.getBand( bandIdx )->getProperty()->m_nblocksx *
110  externalRaster.getBand( bandIdx )->getProperty()->m_nblocksy );
111  }
112 
113  // Allocating the internal structures
114 
115  m_rasterPtr = (te::rst::Raster*)&externalRaster;
116  m_dataPrefetchThreshold = dataPrefetchThreshold;
117 
118  m_maxNumberOfCacheBlocks = std::min( maxNumberOfCacheBlocks, numberOfRasterBlocks );
119  m_maxNumberOfCacheBlocks = std::max( m_maxNumberOfCacheBlocks, (unsigned int)1 );
120 
121  unsigned int blockBIdx = 0;
122  m_blocksPointers.resize( externalRaster.getNumberOfBands() );
123 
124  for( blockBIdx = 0 ; blockBIdx < m_blocksPointers.size() ; ++blockBIdx )
125  {
126  m_blocksPointers[ blockBIdx ].resize( m_globalBlocksNumberY );
127 
128  for( unsigned int blockYIdx = 0 ; blockYIdx < m_globalBlocksNumberY ;
129  ++blockYIdx )
130  {
131  m_blocksPointers[ blockBIdx ][ blockYIdx ].resize( m_globalBlocksNumberX, nullptr );
132  }
133  }
134 
136  {
137  m_threadParams.m_rasterPtr = (te::rst::Raster*)&externalRaster;
138  m_threadParams.m_dataPrefetchThreshold = dataPrefetchThreshold;
141  m_threadParams.m_blockPtr= nullptr;
146  m_threadParams.m_threadDataBlockHandler.reset( new unsigned char[
148 
149  m_threadHandler.reset( new boost::thread( threadEntry, &m_threadParams ) );
150  }
151 
152  return true;
153 }
154 
156 {
157  // Stopping the thread
158 
160  {
161  {
162  boost::lock_guard<boost::mutex> lock(m_threadParams.m_doTaskMutex);
164  m_threadParams.m_doTaskCondVar.notify_one();
165  }
166 
167  m_threadHandler->join();
168  m_threadHandler.reset();
169  }
170 
171  // flushing the ram data, if necessary
172 
173  if( ( m_rasterPtr != nullptr ) &&
175  {
176  unsigned int blockBIdx = 0;
177  unsigned int blockYIdx = 0;
178  unsigned int blockXIdx = 0;
179  void* blockPtr = nullptr;
180 
181  for( blockBIdx = 0 ; blockBIdx < m_blocksPointers.size() ; ++blockBIdx )
182  {
183  for( blockYIdx = 0 ; blockYIdx < m_globalBlocksNumberY ;
184  ++blockYIdx )
185  {
186  for( blockXIdx = 0 ; blockXIdx < m_globalBlocksNumberX ;
187  ++blockXIdx )
188  {
189  blockPtr = m_blocksPointers[ blockBIdx ][ blockYIdx ][ blockXIdx ];
190 
191  if( blockPtr )
192  {
193  m_rasterPtr->getBand( blockBIdx )->write( blockXIdx, blockYIdx,
194  blockPtr );
195  }
196  }
197  }
198  }
199  }
200 
201  m_blocksPointers.clear();
202 
203  unsigned char* blockPtr = nullptr;
204  for( std::vector< unsigned char* >::size_type blocksHandlerIdx = 0 ;
205  blocksHandlerIdx < m_blocksHandler.size() ; ++blocksHandlerIdx )
206  {
207  blockPtr = m_blocksHandler[ blocksHandlerIdx ];
208  if( blockPtr )
209  {
210  delete[]( blockPtr );
211  }
212  }
213  m_blocksHandler.clear();
214 
215  m_blocksFifo.clear();
216  m_threadHandler.reset();
218 
219  initState();
220 }
221 
223  unsigned int x, unsigned int y )
224 {
225  assert( m_rasterPtr );
226  assert( band < m_rasterPtr->getNumberOfBands() );
227  assert( x < m_globalBlocksNumberX );
228  assert( y < m_globalBlocksNumberY );
229  assert( x < (unsigned int)m_rasterPtr->getBand( band )->getProperty()->m_nblocksx );
230  assert( y < (unsigned int)m_rasterPtr->getBand( band )->getProperty()->m_nblocksy );
231 
233 
234  if( m_getBlockPointer_BlkPtr == nullptr )
235  {
236  // Is swapp necessary ?
238  {
239  m_getBlockPointer_BlkPtr = new unsigned char[ m_globalBlockSizeBytes ];
240  m_blocksHandler.push_back( m_getBlockPointer_BlkPtr );
241 
242  // add FIFO information of the new block
243  BlockIndex newBlockFifoIndex;
244  newBlockFifoIndex.m_b = band;
245  newBlockFifoIndex.m_y = y;
246  newBlockFifoIndex.m_x = x;
247  m_blocksFifo.push_back( newBlockFifoIndex );
248  }
249  else
250  {
251  BlockIndex& choosedSwapBlockIndex = m_blocksFifo[
253 
254  m_getBlockPointer_BlkPtr = m_blocksPointers[ choosedSwapBlockIndex.m_b ][
255  choosedSwapBlockIndex.m_y ][ choosedSwapBlockIndex.m_x ];
256  assert( m_getBlockPointer_BlkPtr );
257  m_blocksPointers[ choosedSwapBlockIndex.m_b ][
258  choosedSwapBlockIndex.m_y ][ choosedSwapBlockIndex.m_x ] = nullptr;
259 
260  // writing the block choosed for swap, if necessary
262  {
264  {
265  // request a block writing to the thread
266  {
267  boost::lock_guard<boost::mutex> lock(m_threadParams.m_doTaskMutex);
268 
269  m_threadParams.m_blockB = choosedSwapBlockIndex.m_b;
270  m_threadParams.m_blockX = choosedSwapBlockIndex.m_x;
271  m_threadParams.m_blockY = choosedSwapBlockIndex.m_y;
276  }
277 
278  m_threadParams.m_doTaskCondVar.notify_one();
279 
280  // wait for the block writing request to finish
281  while( ! m_threadParams.m_taskFinished )
282  {
283  boost::unique_lock<boost::mutex> lock(
285 
286  while( ! m_threadParams.m_taskFinished )
287  {
289  }
290  }
291  }
292  else
293  {
294  m_rasterPtr->getBand( choosedSwapBlockIndex.m_b )->write(
295  choosedSwapBlockIndex.m_x, choosedSwapBlockIndex.m_y,
296  m_getBlockPointer_BlkPtr );
297  }
298  }
299 
300  // advances the next swap block fifo index
301  choosedSwapBlockIndex.m_b = band;
302  choosedSwapBlockIndex.m_y = y;
303  choosedSwapBlockIndex.m_x = x;
305  ((unsigned int)m_blocksFifo.size());
306  }
307 
308  // reading the required block
310  {
311  // request a block reading to the thread
312  {
313  boost::lock_guard<boost::mutex> lock(m_threadParams.m_doTaskMutex);
314 
318  m_threadParams.m_blockPtr = nullptr;
322 
323  m_threadParams.m_doTaskCondVar.notify_one();
324  }
325 
326  // wait for the block reading request to finish
327  {
328  boost::unique_lock<boost::mutex> lock(
330 
331  while( ! m_threadParams.m_taskFinished )
332  {
334  }
335  }
336 
338 
340  m_getBlockPointer_BlkPtr = m_threadParams.m_blockPtr;
341  }
342  else
343  {
344  m_rasterPtr->getBand( band )->read( x, y, m_getBlockPointer_BlkPtr );
346  }
347 
348 
349  }
350 
351  return m_getBlockPointer_BlkPtr;
352 }
353 
355 {
356 // std::cout << std::endl << "Thread started" << std::endl;
357 
358  assert( paramsPtr );
359  assert( paramsPtr->m_rasterPtr );
360 
361  // internal data block to exchange
362  unsigned char* internalExchangeBlockPtr = paramsPtr->m_threadDataBlockHandler.get();
363  assert( internalExchangeBlockPtr );
364 
365  int globalReadAheadDirectionVectorX = 0;
366  int globalReadAheadDirectionVectorY = 0;
367  int globalReadAheadDirectionVectorB = 0;
368  bool globalReadAheadBlockReady = false;
369  int globalReadAheadBlockB = 0;
370  int globalReadAheadBlockX = 0;
371  int globalReadAheadBlockY = 0;
372  int lastReadBlockX = 0;
373  int lastReadBlockY = 0;
374  int lastReadBlockB = 0;
375 
376  int currentReadDirectionVectorX = 0;
377  int currentReadDirectionVectorY = 0;
378  int currentReadDirectionVectorB = 0;
379  int nextReadAheadBlkB = 0;
380  int nextReadAheadBlkX = 0;
381  int nextReadAheadBlkY = 0;
382  bool doReadAhead = false;
383 
384  while( true )
385  {
386  // wait for a task
387  boost::unique_lock<boost::mutex> lock( paramsPtr->m_doTaskMutex );
388  while( paramsPtr->m_task == ThreadParameters::InvalidTaskT )
389  {
390  paramsPtr->m_doTaskCondVar.wait( lock );
391  }
392 
393  if( paramsPtr->m_task == ThreadParameters::ReadTaskT )
394  {
395 // std::cout << std::endl << "Starting a read task" << std::endl;
396 
397  assert( paramsPtr->m_blockPtr == nullptr );
398  assert( paramsPtr->m_exchangeBlockPtr );
399 
400  if( globalReadAheadBlockReady
401  && ( globalReadAheadBlockB == (int)paramsPtr->m_blockB )
402  && ( globalReadAheadBlockX == (int)paramsPtr->m_blockX )
403  && ( globalReadAheadBlockY == (int)paramsPtr->m_blockY ) )
404  {
405 // std::cout << std::endl << "Read-ahead block is avaliable, it will be used" << std::endl;
406 
407  // use the read-ahed block
408  paramsPtr->m_blockPtr = internalExchangeBlockPtr;
409  globalReadAheadBlockReady = false;
410  internalExchangeBlockPtr = paramsPtr->m_exchangeBlockPtr;
411 
412 // std::cout << std::endl << "Read-ahead block used." << std::endl;
413  }
414  else
415  {
416 // std::cout << std::endl << "Read-ahead block not avaliable, block will be read from raster" << std::endl;
417 
418  // read from the external raster
419  paramsPtr->m_rasterPtr->getBand( paramsPtr->m_blockB )->read( paramsPtr->m_blockX,
420  paramsPtr->m_blockY, paramsPtr->m_exchangeBlockPtr );
421  paramsPtr->m_blockPtr = paramsPtr->m_exchangeBlockPtr;
422 
423 // std::cout << std::endl << "Block readed from raster." << std::endl;
424  }
425 
426  // notifying the task finishment
427 
428  {
429  boost::lock_guard<boost::mutex> lock( paramsPtr->m_taskFinishedMutex );
430 
431  paramsPtr->m_taskFinished = true;
433 
434  paramsPtr->m_taskFinishedCondVar.notify_one();
435  }
436 
437  // defining if read-ahed must be done
438 
439  if( paramsPtr->m_dataPrefetchThreshold )
440  {
441  currentReadDirectionVectorX = ( ((int)paramsPtr->m_blockX) - lastReadBlockX );
442  currentReadDirectionVectorY = ( ((int)paramsPtr->m_blockY) - lastReadBlockY );
443  currentReadDirectionVectorB = ( ((int)paramsPtr->m_blockB) - lastReadBlockB );
444 
445  doReadAhead = false;
446 
447  if( ( std::abs( currentReadDirectionVectorX ) < 2 ) &&
448  ( std::abs( currentReadDirectionVectorY ) < 2 )
449  && ( std::abs( currentReadDirectionVectorB ) < 2 ) )
450  {
451  globalReadAheadDirectionVectorX += currentReadDirectionVectorX;
452  globalReadAheadDirectionVectorY += currentReadDirectionVectorY;
453  globalReadAheadDirectionVectorB += currentReadDirectionVectorB;
454 
455  if( ((unsigned int)std::abs( globalReadAheadDirectionVectorB )) >
456  paramsPtr->m_dataPrefetchThreshold )
457  {
458  if( globalReadAheadDirectionVectorB > 0 )
459  {
460  nextReadAheadBlkB = ((int)paramsPtr->m_blockB) + 1;
461  --globalReadAheadDirectionVectorB;
462  }
463  else
464  {
465  nextReadAheadBlkB = ((int)paramsPtr->m_blockB) - 1;
466  ++globalReadAheadDirectionVectorB;
467  }
468 
469  if( ( nextReadAheadBlkB >= 0 ) &&
470  ( nextReadAheadBlkB < (int)paramsPtr->m_rasterPtr->getNumberOfBands() ) )
471  doReadAhead = true;
472  else
473  nextReadAheadBlkB = ((int)paramsPtr->m_blockB);
474  }
475 
476  if( ((unsigned int)std::abs( globalReadAheadDirectionVectorX )) >
477  paramsPtr->m_dataPrefetchThreshold )
478  {
479  if( globalReadAheadDirectionVectorX > 0 )
480  {
481  nextReadAheadBlkX = ((int)paramsPtr->m_blockX) + 1;
482  --globalReadAheadDirectionVectorX;
483  }
484  else
485  {
486  nextReadAheadBlkX = ((int)paramsPtr->m_blockX) - 1;
487  ++globalReadAheadDirectionVectorX;
488  }
489 
490  if( ( nextReadAheadBlkX >= 0 ) &&
491  ( nextReadAheadBlkX <
492  paramsPtr->m_rasterPtr->getBand( nextReadAheadBlkB )->getProperty()->m_nblocksx ) )
493  doReadAhead = true;
494  else
495  nextReadAheadBlkX = ((int)paramsPtr->m_blockX);
496  }
497 
498  if( ((unsigned int)std::abs( globalReadAheadDirectionVectorY )) >
499  paramsPtr->m_dataPrefetchThreshold )
500  {
501  if( globalReadAheadDirectionVectorY > 0 )
502  {
503  nextReadAheadBlkY = ((int)paramsPtr->m_blockY) + 1;
504  --globalReadAheadDirectionVectorY;
505  }
506  else
507  {
508  nextReadAheadBlkY = ((int)paramsPtr->m_blockY) - 1;
509  ++globalReadAheadDirectionVectorY;
510  }
511 
512  if( ( nextReadAheadBlkY >= 0 ) &&
513  ( nextReadAheadBlkY <
514  paramsPtr->m_rasterPtr->getBand( nextReadAheadBlkB )->getProperty()->m_nblocksy ) )
515  doReadAhead = true;
516  else
517  nextReadAheadBlkY = ((int)paramsPtr->m_blockY);
518  }
519  }
520  else
521  {
522  globalReadAheadDirectionVectorX = 0;
523  globalReadAheadDirectionVectorY = 0;
524  globalReadAheadDirectionVectorB = 0;
525  }
526 
527  if( doReadAhead )
528  {
529 // std::cout << std::endl << "Reading-ahead a new block" << std::endl;
530 
531  assert( nextReadAheadBlkB < (int)paramsPtr->m_rasterPtr->getNumberOfBands() );
532  assert( nextReadAheadBlkX <
533  paramsPtr->m_rasterPtr->getBand( nextReadAheadBlkB )->getProperty()->m_nblocksx );
534  assert( nextReadAheadBlkY <
535  paramsPtr->m_rasterPtr->getBand( nextReadAheadBlkB )->getProperty()->m_nblocksy );
536 
537  paramsPtr->m_rasterPtr->getBand( nextReadAheadBlkB )->read( nextReadAheadBlkX,
538  nextReadAheadBlkY, internalExchangeBlockPtr );
539 
540  globalReadAheadBlockX = nextReadAheadBlkX;
541  globalReadAheadBlockY = nextReadAheadBlkY;
542  globalReadAheadBlockB = nextReadAheadBlkB;
543  globalReadAheadBlockReady = true;
544 
545 // std::cout << std::endl << "Read-ahead block reading completed." << std::endl;
546  }
547  }
548 
549  lastReadBlockX = (int)paramsPtr->m_blockX;
550  lastReadBlockY = (int)paramsPtr->m_blockY;
551  lastReadBlockB = (int)paramsPtr->m_blockB;
552  }
553  else if( paramsPtr->m_task == ThreadParameters::WriteTaskT )
554  {
555 // std::cout << std::endl << "Starting a write task" << std::endl;
556 
557  assert( paramsPtr->m_blockPtr );
558  assert( paramsPtr->m_exchangeBlockPtr == nullptr );
559 
560  paramsPtr->m_rasterPtr->getBand( paramsPtr->m_blockB )->write( paramsPtr->m_blockX,
561  paramsPtr->m_blockY, paramsPtr->m_blockPtr );
562 
563  // notifying the task finishment
564 
565  paramsPtr->m_taskFinished = true;
567  paramsPtr->m_taskFinishedCondVar.notify_one();
568  }
569  else if( paramsPtr->m_task == ThreadParameters::SuicideTastT )
570  {
571 // std::cout << std::endl << "Thread ending" << std::endl;
572  return;
573  }
574 
575 // std::cout << std::endl << "Task ended" << std::endl;
576  }
577 }
578 
579 
unsigned int band
boost::mutex m_taskFinishedMutex
used by the thread to inform a task finishment.
TECOMMONEXPORT unsigned long long int GetTotalVirtualMemory()
Returns the amount of total virtual memory (bytes) that can be claimed by the current process (physic...
unsigned int m_globalBlocksNumberX
The maximum number of blocks (X axis) for all bands.
Internal read/write thread execution parameters.
void * getBlockPointer(unsigned int band, unsigned int x, unsigned int y)
Returns a pointer to the required data block.
unsigned int m_globalBlockSizeBytes
The maximum block size for all bands.
bool m_taskFinished
true when the thread has finished the required task.
int m_nblocksx
The number of blocks in x.
Definition: BandProperty.h:145
int m_nblocksy
The number of blocks in y.
Definition: BandProperty.h:146
unsigned int m_dataPrefetchThreshold
The user defined read-ahead threshold.
boost::scoped_array< unsigned char > m_threadDataBlockHandler
A extra block used in exchange when a read-ahead task is performed.
unsigned int m_x
Block index over the X axis.
unsigned int m_y
Block index over the Y axis.
void initState()
Initialize this instance to an initial state.
RAM cached and tiled raster band blocks manager.
te::common::AccessPolicy getAccessPolicy() const
Returns the raster access policy.
te::rst::Raster * m_rasterPtr
External raster pointer.
An abstract class for raster data strucutures.
virtual std::size_t getNumberOfBands() const =0
Returns the number of bands (dimension of cells attribute values) in the raster.
BandProperty * getProperty()
Returns the band property.
ThreadParameters m_threadParams
The internal thread execution parameters.
unsigned int m_maxNumberOfCacheBlocks
The maximum number of cache blocks.
virtual void write(int x, int y, void *buffer)=0
It writes a data block from the specified buffer.
bool initialize(const te::rst::Raster &externalRaster, const unsigned char maxMemPercentUsed, const unsigned int dataPrefetchThreshold)
Initialize this instance to an initial state.
virtual const Band * getBand(std::size_t i) const =0
Returns the raster i-th band.
unsigned int m_globalBlocksNumberY
The maximum number of blocks (Y axis) for all bands.
std::vector< std::vector< std::vector< unsigned char * > > > m_blocksPointers
3D Matrix of block pointers indexed as [band][blockYIndex][blockXIndex].
te::rst::Raster * m_rasterPtr
External raster pointer.
m_blockPtr must point to the block to be written, m_exchangeBlockPtr must be zero.
TECOMMONEXPORT unsigned long long int GetTotalPhysicalMemory()
Returns the amount of total physical memory (bytes).
unsigned int m_dataPrefetchThreshold
The read-ahead data prefetch threshold (0-will disable prefetch, 1-data always prefetched, higher values will do prefetch when necessary).
virtual void read(int x, int y, void *buffer) const =0
It reads a data block to the specified buffer.
unsigned int m_blocksFifoNextSwapBlockIndex
The next block swapp index over m_blocksFifo.
m_exchangeBlockPtr must point to a valid exchange block (it will be keept inside the thread for furth...
static void threadEntry(ThreadParameters *paramsPtr)
Thread entry.
std::unique_ptr< boost::thread > m_threadHandler
The internal thread handler.
unsigned char * m_exchangeBlockPtr
Exchange block pointer.
boost::condition_variable m_taskFinishedCondVar
Used to wait for the required task finishment.
std::vector< BlockIndex > m_blocksFifo
blocks swap FIFO.
std::vector< unsigned char * > m_blocksHandler
Cache blocks handler.
TECOMMONEXPORT unsigned long long int GetUsedVirtualMemory()
Returns the amount of used virtual memory (bytes) for the current process (physical + swapped)...
virtual int getBlockSize() const
It returns the number of bytes ocuppied by a data block.
TaskType m_task
The required task to be performed (read/write/exit).
boost::mutex m_doTaskMutex
Used when wakenning the thread to perform some task.
boost::condition_variable m_doTaskCondVar
Used by the thread when awakenning to perform some task.