note description: "Concurrent pool for SCOOP concurrency mode." date: "$Date$" revision: "$Revision$" class CONCURRENT_POOL [G -> CONCURRENT_POOL_ITEM] inherit HTTPD_DEBUG_FACILITIES create make feature {NONE} -- Initialization make (n: INTEGER) do capacity := n create items.make_empty (n) create busy_items.make_empty (n) end feature -- Access count: INTEGER -- Number of concurrent items managed by Current pool. capacity: INTEGER -- Maximum number of concurrent items managed by Current pool. feature -- Status report is_full: BOOLEAN -- Pool is full? do Result := count >= capacity end is_empty: BOOLEAN -- No concurrent item waiting in current pool. do Result := count = 0 end stop_requested: BOOLEAN -- Current pool received a request to terminate. feature -- Access separate_item (a_factory: separate CONCURRENT_POOL_FACTORY [G]): detachable separate G -- Reused, or new separate item of type {G} created by `a_factory'. require is_not_full: not is_full local i,n,pos: INTEGER lst: like busy_items l_item: detachable separate G do if not stop_requested then from lst := busy_items pos := -1 i := 0 n := lst.count - 1 until i > n or l_item /= Void or pos >= 0 loop if not lst [i] then -- is free (i.e not busy) pos := i if items.valid_index (pos) then l_item := items [pos] if l_item /= Void then busy_items [pos] := True end end if l_item = Void then -- Empty, then let's create one. l_item := a_factory.new_separate_item register_item (l_item) items [pos] := l_item end end i := i + 1 end if l_item = Void then -- Pool is FULL ... check overcapacity: False end else debug ("pool", "dbglog") dbglog ("Lock pool item #" + pos.out + " (free:"+ (capacity - count).out +"))") end count := count + 1 busy_items [pos] := True Result := l_item a_factory.update_item (l_item) end end end feature -- Basic operation gracefull_stop -- Request the Current pool to terminate. do stop_requested := True end feature {NONE} -- Internal items: SPECIAL [detachable separate G] -- List of concurrent items. busy_items: SPECIAL [BOOLEAN] -- Map of items being proceed. feature {CONCURRENT_POOL_ITEM} -- Change release_item (a_item: separate G) -- Unregister `a_item' from Current pool. require count > 0 local i,n,pos: INTEGER lst: like items do -- release handler for reuse from lst := items i := 0 n := lst.count - 1 until i > n or lst [i] = a_item loop i := i + 1 end if i <= n then pos := i busy_items [pos] := False count := count - 1 --reuse items [pos] := Void debug ("pool", "dbglog") dbglog ("Released pool item #" + i.out + " (free:"+ (capacity - count).out +"))") end else check known_item: False end end end feature -- Change set_count (n: INTEGER) -- Set capacity of Current pool to `n'. local g: detachable separate G do capacity := n items.fill_with (g, 0, n - 1) busy_items.fill_with (False, 0, n - 1) end terminate -- Terminate current pool. local l_items: like items do l_items := items l_items.wipe_out end feature {NONE} -- Implementation register_item (a_item: separate G) -- Adopt `a_item' in current pool. do a_item.set_pool (Current) end note copyright: "2011-2016, Jocelyn Fiat, Javier Velilla, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software 5949 Hollister Ave., Goleta, CA 93117 USA Telephone 805-685-1006, Fax 805-685-6869 Website http://www.eiffel.com Customer support http://support.eiffel.com ]" end