/pliant/language/schedule/resourcesem.pli
 
 1  # Copyright  Hubert Tonneau  hubert.tonneau@pliant.cx 
 2  # 
 3  # This program is free software; you can redistribute it and/or 
 4  # modify it under the terms of the GNU General Public License version 2 
 5  # as published by the Free Software Foundation. 
 6  # 
 7  # This program is distributed in the hope that it will be useful, 
 8  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 9  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 10  # GNU General Public License for more details. 
 11  # 
 12  # You should have received a copy of the GNU General Public License 
 13  # version 2 along with this program; if not, write to the Free Software 
 14  # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. 
 15   
 16  module "/pliant/language/unsafe.pli" 
 17  module "/pliant/language/os.pli" 
 18  module "/pliant/language/schedule/threads_engine.pli" 
 19   
 20  constant busy_wait false # processor_count>1 
 21   
 22   
 23  if busy_wait 
 24    function wait_a_bit 
 25      for (var Int i) 0 10 
 26        void 
 27  else 
 28    function wait_a_bit 
 29      os_yield 
 30   
 31   
 32  type ResourceSem 
 33    field Int current 
 34    field Int maxi 
 35    field ThreadQueue queue 
 36     
 37   
 38  function build sem 
 39    arg_w ResourceSem sem 
 40    sem current := 0 
 41    sem maxi := 1 
 42   
 43  method sem safe_read_current -> c 
 44    arg_rw ResourceSem sem ; arg Int c 
 45    part read 
 46      := atomic_read_and_set sem:current undefined 
 47      if c=undefined 
 48        wait_a_bit 
 49        restart read 
 50   
 51   
 52  method s configure maxi 
 53    arg_rw ResourceSem s ; arg Int maxi 
 54    maxi := maxi 
 55   
 56  method s query current maxi 
 57    arg_rw ResourceSem s ; arg_w Int current maxi 
 58    part read 
 59      current := current 
 60      if current=undefined 
 61        restart read 
 62    maxi := maxi 
 63   
 64   
 65  method sem request n 
 66    arg_rw ResourceSem sem ; arg Int n 
 67    var Int := sem safe_read_current 
 68    if (c<>and c+n>sem:maxi) or not sem:queue:is_empty 
 69      part wait 
 70        sem:queue add_current_thread n 
 71        sem current := c 
 72        stop_current_thread 
 73        := sem safe_read_current 
 74        if c<>and c+n>sem:maxi 
 75          restart wait 
 76    sem current := c+n 
 77   
 78   
 79  method sem release n 
 80    arg_rw ResourceSem sem ; arg Int n 
 81    var uInt := sem safe_read_current 
 82    sem:queue restart_some_threads sem:maxi-(c-n) ((addressof sem:current) map uInt) (cast c-uInt) 
 83   
 84   
 85  method sem nowait_request n -> success 
 86    arg_rw ResourceSem sem ; arg Int n ; arg CBool success 
 87    var Int := sem safe_read_current 
 88    if c+n<=sem:maxi and sem:queue:is_empty 
 89      sem current := c+n 
 90      success := true 
 91    else 
 92      sem current := c 
 93      success := false 
 94   
 95   
 96  export ResourceSem '. configure' '. query' 
 97  export '. request' '. release' '. nowait_request'