Ignore:
File:
1 edited

Legend:

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

    r95707a3 rb2f3880  
    1 //                               -*- Mode: C -*-
    2 //
     1//
    32// Cforall Version 1.0.0 Copyright (C) 2022 University of Waterloo
    4 // 
     3//
    54// The contents of this file are covered under the licence agreement in the
    65// file "LICENCE" distributed with Cforall.
    76//
    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 // 
     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//
    1615
    1716#pragma once
     
    1918#include <monitor.hfa>
    2019
    21 // Plan 9 inheritance does not work with monitors. Two monitor locks are created.
     20// Simple barrier based on a monitor
     21monitor 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;
    2225
    23 monitor barrier {
    24         unsigned int group, arrivals;                                           // group size, arrival counter
    25         condition c;                                                                            // wait for group to form
     26        // Current count (counting backwards)
     27        unsigned count;
     28
     29        // Barrier uses internal scheduling
     30        condition c;
    2631};
    2732
    28 static inline void ?{}( barrier & b, unsigned int group ) {
    29         b.group = b.arrivals = group;                                           // arrivals count backward
     33// Constructor
     34void ?{}( barrier & this, unsigned width ) {
     35        this.width = width;
     36        this.count = width; // Count backwards so initialize at width
    3037}
    3138
    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.
    34 static 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
     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
     46static 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
    4559}
Note: See TracChangeset for help on using the changeset viewer.