P99
p99_count.h
Go to the documentation of this file.
1 /* This may look like nonsense, but it really is -*- mode: C; coding: utf-8 -*- */
2 /* */
3 /* Except for parts copied from previous work and as explicitly stated below, */
4 /* the author and copyright holder for this work is */
5 /* (C) copyright 2012, 2016 Jens Gustedt, INRIA, France */
6 /* */
7 /* This file is free software; it is part of the P99 project. */
8 /* */
9 /* Licensed under the Apache License, Version 2.0 (the "License"); */
10 /* you may not use this file except in compliance with the License. */
11 /* You may obtain a copy of the License at */
12 /* */
13 /* http://www.apache.org/licenses/LICENSE-2.0 */
14 /* */
15 /* Unless required by applicable law or agreed to in writing, software */
16 /* distributed under the License is distributed on an "AS IS" BASIS, */
17 /* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
18 /* See the License for the specific language governing permissions and */
19 /* limitations under the License. */
20 /* */
21 #ifndef P99_COUNT_H
22 #define P99_COUNT_H
23 
24 #include "p99_futex.h"
25 
41 #ifdef P00_DOXYGEN
42 struct p99_count {};
43 #else
44 typedef p99_futex p99_count;
45 #endif
46 
50 # define P99_COUNT_INITIALIZER P99_FUTEX_INITIALIZER
51 
57 p99_count* p99_count_init(p99_count* p00_c, unsigned p00_v) {
58  return p99_futex_init(p00_c, p00_v);
59 }
60 
61 #define p99_count_init(...) P99_CALL_DEFARG(p99_count_init, 2, __VA_ARGS__)
62 #define p99_count_init_defarg_1() 0U
63 
66  p99_futex_destroy(p00_c);
67 }
68 
74 #define P99_ACCOUNT(COUNT) \
75 P00_BLK_DECL(p99_count*, p00Mcount, &(COUNT)) \
76 P99_PROTECTED_BLOCK(p99_count_inc(p00Mcount), p99_count_dec(p00Mcount))
77 
85 p99_inline unsigned p99_count_inc(p99_count volatile* p00_c, unsigned p00_hm) {
86  return p99_futex_add(p00_c, p00_hm, 0U, 0U, 0U, 0U);
87 }
88 
89 #define p99_count_inc(...) P99_CALL_DEFARG(p99_count_inc, 2, __VA_ARGS__)
90 #define p99_count_inc_defarg_1() (1U)
91 
99 P00_FUTEX_INLINE(p99_count_inc_conditionally)
100 unsigned p99_count_inc_conditionally(p99_count volatile* p00_c, unsigned p00_hm) {
101  unsigned p00_ret = 0;
102  P99_FUTEX_COMPARE_EXCHANGE(p00_c, p00_act,
103  /* never wait */
104  true,
105  /* only do something if positive */
106  (!p00_act ? 0U : p00_act + p00_hm),
107  /* capture the state for return, but
108  never wakeup and waiters */
109  ((p00_ret = p00_act), 0), 0);
110  return p00_ret;
111 }
112 
113 #define p99_count_inc_conditionally(...) P99_CALL_DEFARG(p99_count_inc_conditionally, 2, __VA_ARGS__)
114 #define p99_count_inc_conditionally_defarg_1() (1U)
115 
120 p99_inline unsigned p99_count_value(p99_count volatile* p00_c) {
121  return p99_futex_load(p00_c);
122 }
123 
124 
135 unsigned p99_count_dec(p99_count volatile* p00_c, unsigned p00_hm) {
136  unsigned ret = p99_futex_add(p00_c, -(signed)p00_hm, 0U, 1U, 0U, P99_FUTEX_MAX_WAITERS);
137  return ret - p00_hm;
138 }
139 
140 #define p99_count_dec(...) P99_CALL_DEFARG(p99_count_dec, 2, __VA_ARGS__)
141 #define p99_count_dec_defarg_1() (1U)
142 
149 P00_FUTEX_INLINE(p99_count_wait)
150 void p99_count_wait(p99_count volatile* p00_c) {
151  P99_FUTEX_COMPARE_EXCHANGE(p00_c, p00_act, !p00_act, p00_act, 0U, 0U);
152 }
153 
159 #endif
void
void void
Definition: p99_bitset.h:84
p99_futex.h
p99_futex::p99_futex_destroy
void p99_futex_destroy(p99_futex *p00_c)
Destroy an p99_futex object.
p99_futex
A counter similar to a conditional variable that allows atomic increment and decrement and to wait fo...
Definition: p99_futex.h:163
P99_BLOCK_DOCUMENT
#define P99_BLOCK_DOCUMENT
Add some default documentation and links to the following block macro.
Definition: p99_block.h:732
p99_count::p99_count_wait
void p99_count_wait(p99_count volatile *p00_c)
wait until the p00_c counter falls to 0.
Definition: p99_count.h:150
p99_count_init
#define p99_count_init(...)
Definition: p99_count.h:61
p99_inline
#define p99_inline
Try to force a function always to be inlined.
Definition: p99_compiler.h:496
p99_futex::P99_FUTEX_COMPARE_EXCHANGE
#define P99_FUTEX_COMPARE_EXCHANGE(FUTEX, ACT, EXPECTED, DESIRED, WAKEMIN, WAKEMAX)
a catch all macro to operate on p99_futex
Definition: p99_futex.h:563
unsigned
void unsigned(void)
P99_DEFARG_DOCU
#define P99_DEFARG_DOCU(NAME)
Provide a documentation section to a function defined with P99_CALL_DEFARG.
Definition: p99_defarg.h:318
p99_futex::p99_futex_load
unsigned p99_futex_load(p99_futex volatile *p00_fut)
Obtain the value of futex p00_fut atomically.
p99_count::p99_count_inc_conditionally
#define p99_count_inc_conditionally(...)
increment the counter p00_c atomically by p00_hm but only if it is not zero before.
Definition: p99_count.h:100
p99_count::p99_count_value
unsigned p99_count_value(p99_count volatile *p00_c)
Obtain the value of counter p00_c atomically.
Definition: p99_count.h:120
p99_futex::p99_futex_add
unsigned p99_futex_add(p99_futex volatile *p00_fut, unsigned p00_hmuch, unsigned p00_cstart, unsigned p00_clen, unsigned p00_wmin, unsigned p00_wmax)
increment the counter of p00_fut atomically by p00_hmuch.
p99_count
A counter that allows atomic increment and decrement and a wait for the value 0.
Definition: p99_count.h:42
p99_futex::P99_FUTEX_MAX_WAITERS
#define P99_FUTEX_MAX_WAITERS
the maximum number of waiters that an p99_futex may have
Definition: p99_futex.h:178
p99_futex::p99_futex_init
p99_futex * p99_futex_init(p99_futex *p00_c, unsigned p00_ini)
Initialize an p99_futex object.
p99_count_destroy
void p99_count_destroy(p99_count *p00_c)
Definition: p99_count.h:65
p99_count::p99_count_dec
#define p99_count_dec(...)
decrement the counter p00_c atomically by p00_hm.
Definition: p99_count.h:135
p99_count::p99_count_inc
#define p99_count_inc(...)
increment the counter counter atomically by p00_hm.
Definition: p99_count.h:85