Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/concurrency/barrier.hfa

    rb2f3880 r95707a3  
    1 //
     1//                               -*- Mode: C -*-
     2//
    23// Cforall Version 1.0.0 Copyright (C) 2022 University of Waterloo
    3 //
     4// 
    45// The contents of this file are covered under the licence agreement in the
    56// file "LICENCE" distributed with Cforall.
    67//
    7 // barrier.hfa -- simple barrier implemented from monitors
    8 //
    9 // Author           : Thierry Delisle
    10 // Created On       : Thu Mar 31 16:51:35 2022
    11 // 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 : Wed Nov 13 12:37:04 2024
     14// Update Count     : 9
     15// 
    1516
    1617#pragma once
     
    1819#include <monitor.hfa>
    1920
    20 // Simple barrier based on a monitor
     21// Plan 9 inheritance does not work with monitors. Two monitor locks are created.
     22
    2123monitor 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
    3126};
    3227
    33 // Constructor
    34 void ?{}( barrier & this, unsigned width ) {
    35         this.width = width;
    36         this.count = width; // Count backwards so initialize at width
     28static inline void ?{}( barrier & b, unsigned int group ) {
     29        b.group = b.arrivals = group;                                           // arrivals count backward
    3730}
    3831
    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
     32// Returns a value indicating the reverse order the threads arrived, i.e. last thread returns 0 (and does not block)
     33// last is an optional hook that is called by the Gth thread before unblocking the other threads.
     34static inline unsigned int block( barrier & mutex b, fptr_t last = (fptr_t)0 ) with( b ) {
     35        arrivals -= 1;                                                                          // prefix decrement so last is 0 not 1
     36        unsigned arrived = b.arrivals;                                          // note arrival order
     37        if ( arrivals != 0 ) {                                                          // wait for group to form
     38                wait( b.c );
     39        } else {                                                                                        // group formed
     40                if ( last ) last();                                                             // safe to call
     41                signal_all( c );                                                                // unblock group
     42                arrivals = group;                                                               // reset
     43        } // if
     44        return arrived;                                                                         // return arrival order
    5945}
Note: See TracChangeset for help on using the changeset viewer.