source: libcfa/src/concurrency/monitor.hfa

Last change on this file was 8a97248, checked in by Peter A. Buhr <pabuhr@…>, 14 months ago

switch from old trait syntax to new trait syntax using forall clause

  • Property mode set to 100644
File size: 4.5 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2016 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// monitor --
8//
9// Author           : Thierry Delisle
10// Created On       : Thd Feb 23 12:27:26 2017
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Thu Feb  2 11:29:21 2023
13// Update Count     : 12
14//
15
16#pragma once
17
18#include <stddef.h>
19
20#include <assert.h>
21#include "invoke.h"
22#include "stdlib.hfa"
23
24forall( T & )
25trait is_monitor {
26        monitor$ * get_monitor( T & );
27        void ^?{}( T & mutex );
28};
29
30static inline void ?{}(monitor$ & this) with( this ) {
31        lock{};
32        entry_queue{};
33        signal_stack{};
34        owner         = 0p;
35        recursion     = 0;
36        mask.accepted = 0p;
37        mask.data     = 0p;
38        mask.size     = 0;
39        dtor_node     = 0p;
40}
41
42static inline void ^?{}(monitor$ & ) {}
43
44struct monitor_guard_t {
45        monitor$ **     m;
46        __lock_size_t           count;
47        __monitor_group_t prev;
48};
49
50void ?{}( monitor_guard_t & this, monitor$ ** m, __lock_size_t count, void (*func)() );
51void ?{}( monitor_guard_t & this, monitor$ ** m, __lock_size_t count );
52void ^?{}( monitor_guard_t & this );
53
54struct monitor_dtor_guard_t {
55        monitor$ *    m;
56        __monitor_group_t prev;
57        bool join;
58};
59
60void ?{}( monitor_dtor_guard_t & this, monitor$ ** m, void (*func)(), bool join );
61void ^?{}( monitor_dtor_guard_t & this );
62
63/*
64static inline forall( T & | sized(T) | { void ^?{}( T & mutex ); } )
65void delete( T * th ) {
66        if(th) ^(*th){};
67        free( th );
68}
69*/
70
71static inline forall( T & | sized(T) | { void ^?{}( T & mutex ); } )
72void adelete( T arr[] ) {
73        if ( arr ) {                                                                            // ignore null
74                size_t dim = malloc_size( arr ) / sizeof( T );
75                for ( int i = dim - 1; i >= 0; i -= 1 ) {               // reverse allocation order, must be unsigned
76                        ^(arr[i]){};                                                            // run destructor
77                } // for
78                free( arr );
79        } // if
80} // adelete
81
82//-----------------------------------------------------------------------------
83// Internal scheduling
84
85struct __condition_criterion_t {
86        // Whether or not the criterion is met (True if met)
87        bool ready;
88
89        // The monitor this criterion concerns
90        monitor$ * target;
91
92        // The parent node to which this criterion belongs
93        struct __condition_node_t * owner;
94
95        // Intrusive linked list Next field
96        __condition_criterion_t * next;
97};
98
99static inline __condition_criterion_t * & get_next( __condition_criterion_t & this ) {
100        return this.next;
101}
102
103struct __condition_node_t {
104        // Thread that needs to be woken when all criteria are met
105        thread$ * waiting_thread;
106
107        // Array of criteria (Criterions are contiguous in memory)
108        __condition_criterion_t * criteria;
109
110        // Number of criterions in the criteria
111        __lock_size_t count;
112
113        // Intrusive linked list Next field
114        __condition_node_t * next;
115
116        // Custom user info accessible before signalling
117        uintptr_t user_info;
118};
119
120static inline __condition_node_t * & get_next( __condition_node_t & this ) {
121        return this.next;
122}
123
124// void ?{}(__condition_node_t & this, thread$ * waiting_thread, __lock_size_t count, uintptr_t user_info );
125// void ?{}(__condition_criterion_t & this );
126// void ?{}(__condition_criterion_t & this, monitor$ * target, __condition_node_t * owner );
127
128struct condition {
129        // Link list which contains the blocked threads as-well as the information needed to unblock them
130        __queue_t(__condition_node_t) blocked;
131
132        // Array of monitor pointers (Monitors are NOT contiguous in memory)
133        monitor$ ** monitors;
134
135        // Number of monitors in the array
136        __lock_size_t monitor_count;
137};
138
139static inline void ?{}( condition & this ) {
140        this.monitors = 0p;
141        this.monitor_count = 0;
142}
143
144static inline void ^?{}( condition & this ) {
145        free( this.monitors );
146}
147
148              void wait        ( condition & this, uintptr_t user_info = 0 );
149static inline bool is_empty    ( condition & this ) { return this.blocked.head == 1p; }
150              bool signal      ( condition & this );
151              bool signal_block( condition & this );
152static inline bool signal_all  ( condition & this ) { bool ret = false; while(!is_empty(this)) { ret = signal(this) || ret; } return ret; }
153         uintptr_t front       ( condition & this );
154
155//-----------------------------------------------------------------------------
156// External scheduling
157
158struct __acceptable_t {
159        inline struct __monitor_group_t;
160        bool is_dtor;
161};
162
163void __waitfor_internal( const __waitfor_mask_t & mask, int duration );
164
165// lock and unlock routines for mutex statements to use
166void lock( monitor$ * this );
167void unlock( monitor$ * this );
168
169// Local Variables: //
170// mode: c //
171// tab-width: 4 //
172// End: //
Note: See TracBrowser for help on using the repository browser.