Changeset a3af522
- Timestamp:
- Nov 11, 2024, 10:32:08 PM (30 hours ago)
- Branches:
- master
- Children:
- b5f1e850
- Parents:
- 41882628
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libcfa/src/concurrency/barrier.hfa
r41882628 ra3af522 1 // 1 // -*- Mode: C -*- 2 // 2 3 // Cforall Version 1.0.0 Copyright (C) 2022 University of Waterloo 3 // 4 // 4 5 // The contents of this file are covered under the licence agreement in the 5 6 // file "LICENCE" distributed with Cforall. 6 7 // 7 // barrier.hfa -- simple barrier implemented from monitors8 // 9 // Author : Thierry Delisle10 // Created On : Thu Mar 31 16:51:35 202211 // Last Modified By : 12 // Last Modified On : 13 // Update Count : 14 // 8 // barrier.hfa -- simple barrier implemented using a monitor 9 // 10 // Author : Peter A. Buhr 11 // Created On : Sun Nov 10 08:07:35 2024 12 // Last Modified By : Peter A. Buhr 13 // Last Modified On : Sun Nov 10 08:11:55 2024 14 // Update Count : 3 15 // 15 16 16 17 #pragma once … … 18 19 #include <monitor.hfa> 19 20 20 // Simple barrier based on a monitor 21 // Plan 9 inheritance does not work with monitors. Two monitor locks are created. 22 21 23 monitor barrier { 22 // Number of threads blocking needed to unblock the barrier 23 // Unsigned should be enough, I don't expect use cases with 2^32 thread barriers. 24 unsigned width; 25 26 // Current count (counting backwards) 27 unsigned count; 28 29 // Barrier uses internal scheduling 30 condition c; 24 unsigned int group, arrivals; // group size, arrival counter 25 condition c; // wait for group to form 31 26 }; 32 27 33 28 // Constructor 34 void ?{}( barrier & this, unsigned width ) { 35 this.width = width; 36 this.count = width; // Count backwards so initialize at width 29 void ?{}( barrier & b, unsigned group ) { 30 b.group = b.arrivals = group; // count backwards 37 31 } 38 32 39 // block until the number of threads needed have blocked 40 // returns an value indicating the reverse order the threads arrived in 41 // i.e. last thread will return 0 (and not block) 42 // second last thread returns 1 43 // etc. 44 // last is an optional hook that will be called by the last thread 45 // before unblocking the others 46 static inline unsigned block(barrier & mutex this, fptr_t last = (fptr_t)0 ) { 47 this.count -= 1; // prefix decrement so we the last is 0 and not 1 48 unsigned arrival = this.count; // Note arrival order 49 if(arrival == 0) { 50 if(last) last(); 51 // If arrived last unblock everyone and reset 52 signal_all(this.c); 53 this.count = this.width; 54 } else { 55 // Otherwise block 56 wait(this.c); 57 } 58 return arrival; // return arrival order 33 // Returns a value indicating the reverse order the threads arrived i.e. last thread returns 0 (and does not block) 34 // last is an optional hook that is called by the last thread before unblocking the others. 35 static inline unsigned block( barrier & mutex b, fptr_t last = (fptr_t)0 ) with( b ) { 36 arrivals -= 1; // prefix decrement so last is 0 not 1 37 unsigned arrived = b.arrivals; // note arrival order 38 if ( arrivals != 0 ) { // wait for group to form 39 wait( b.c ); 40 } else { // group formed 41 if ( last ) last(); // safe to call 42 signal_all( c ); // unblock group 43 arrivals = group; // reset 44 } // if 45 return arrived; // return arrival order 59 46 }
Note: See TracChangeset
for help on using the changeset viewer.