Releasing-request problem

  1. /* .. One solution to the releasing-request problem */
  2. // this is a 'non-releasing' routine requesting releasing
  3. routine_a()
  4. {
  5.     mutex_lock(mutex);
  6.     // ...
  7.     mutex_lock(mutex_r);
  8.     flag = 1;
  9.     request();    // notify the releasor
  10.     cond_wait(cond_r, mutex_r);
  11.     flag = 0;
  12.     mutex_unlock(mutex_r);
  13.    
  14.     // ...
  15.     mutex_unlock(mutex);
  16. }
  17. // this is the 'releasing' routine
  18. routine_b()
  19. {
  20. again:
  21.     if (flag)
  22.     {
  23.         mutex_lock(mutex_r);
  24.         // needs to check again if the response is actually wanted (check the flag again)
  25.         if (flag)
  26.         {
  27.             response();          
  28.             cond_signal(cond_r);
  29.             mutex_unlock(mutex_r);
  30.         }
  31.         else
  32.         {
  33.             mutex_unlock(mutex_r);
  34.             goto again;
  35.         }
  36.     }
  37.     else
  38.     {
  39.         if (mutex_lock(mutex, timeout) == success)   // a timing-out relaxation needed to avoid deadlock
  40.         {
  41.             // common releasing procedure
  42.             mutex_unlock(mutex);
  43.         }
  44.         else
  45.         {
  46.              goto again;
  47.         }
  48.     }
  49. }
  50. // this is another 'non-releasing' routine
  51. routine_c()
  52. {
  53.     mutex_lock(mutex);
  54.     // ...
  55.     mutex_unlock(mutex);
  56. }
  57. /* .. Another way to solve the releasing-request problem */
  58. // this is a 'non-releasing' routine requesting releasing
  59. routine_a()
  60. {
  61.     mutex_lock(mutex);

  62.     // disable scheduling until cond_wait is waiting so that the execution of the following code is not interrupted
  63.     disable_scheduling();  // to protect critical data
  64.     request();    // notify the releasor (through message)
  65.     flag = 1; 
  66.     cond_wait(cond, mutex);
  67.     flag = 0;
  68.     mutex_unlock(mutex);
  69. }
  70. // this is the 'releasing' routine
  71. routine_b()
  72. {
  73. again:
  74.     if (flag)
  75.     {
  76.         response();
  77.         cond_signal(cond);
  78.     }
  79.     else
  80.     {
  81.         if (mutex_lock(mutex, timeout) == success)  // relaxation
  82.         {
  83.             // common releasing procedure
  84.             // ...
  85.             mutex_unlock(mutex);
  86.         }
  87.         else goto again;
  88.     }
  89. }

In this problem, one routine acts as a releasing requestor, it notifies another routine by sending a signal and then waits for it to release the resource. On making the request,  the mutex is unlocked, so that the routine to perform the releasing in another thread can proceed. However, any other thread that doesn't have this privilege (not to release the resource, just as the requestor itself)  should be blocked during this process.

 

2009.11

Problem description: A mutual exclusive resource R is acquired and released by calling its Acquire and Release method respectively. The calling methods can reside in different threads.

These two methods should offer a proper mechanism to manage clients' accessing and using this resource.

A solution so far that is deemed able to address all formerly existing problems:

 

R { mtxAcq = new Mutex(); mtxAR = new Mutex(); condRel = new Cond(); } R.Acquire() { mtxAcq.Get(); mtxAR.Get(); ... if (CanPreempt()) { Request(); CondWait(condRel, mtxAR); } ... mtxAR.Put(); mtxAcq.Put(); } R.Release() { mtxAR.Get(); R.ReleaseWork(); CondSig(condRel); mtxAR.Put(); } R.IrrelevantRountine() { mtxAcq.Get(); mtxAR.Get(); // do its jobs... mtxAR.Put(); mtxAcq.Put(); }

你可能感兴趣的:(thread,c,Signal,methods)