GCC Code Coverage Report


Directory: cvmfs/
File: cvmfs/util/future.h
Date: 2025-06-29 02:35:41
Exec Total Coverage
Lines: 27 30 90.0%
Branches: 8 14 57.1%

Line Branch Exec Source
1 /**
2 * This file is part of the CernVM File System.
3 */
4
5 #ifndef CVMFS_UTIL_FUTURE_H_
6 #define CVMFS_UTIL_FUTURE_H_
7
8 #include <pthread.h>
9
10 #include <cassert>
11 #include <cstddef>
12
13 #include "util/mutex.h"
14 #include "util/single_copy.h"
15
16 #ifdef CVMFS_NAMESPACE_GUARD
17 namespace CVMFS_NAMESPACE_GUARD {
18 #endif
19
20 /**
21 * This is a simple implementation of a Future wrapper template.
22 * It is used as a proxy for results that are computed asynchronously and might
23 * not be available on the first access.
24 * Since this is a very simple implementation one needs to use the Future's
25 * Get() and Set() methods to obtain the containing data resp. to write it.
26 * Note: More than a single call to Set() is prohibited!
27 * If Get() is called before Set() the calling thread will block until
28 * the value has been set by a different thread.
29 *
30 * @param T the value type wrapped by this Future template
31 */
32 template<typename T>
33 class Future : SingleCopy {
34 public:
35 786 Future() : object_was_set_(false) {
36 786 int retval = pthread_mutex_init(&mutex_, NULL);
37
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 786 times.
786 assert(retval == 0);
38 786 retval = pthread_cond_init(&object_set_, NULL);
39
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 786 times.
786 assert(retval == 0);
40 786 }
41
42 786 ~Future() {
43 786 int retval = pthread_cond_destroy(&object_set_);
44
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 786 times.
786 assert(retval == 0);
45 786 retval = pthread_mutex_destroy(&mutex_);
46
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 786 times.
786 assert(retval == 0);
47 786 }
48
49 /**
50 * Save an asynchronously computed value into the Future. This potentially
51 * unblocks threads that already wait for the value.
52 * @param object the value object to be set
53 */
54 786 void Set(const T &object) {
55 786 MutexLockGuard guard(mutex_);
56
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 786 times.
786 assert(!object_was_set_);
57 786 object_ = object;
58 786 object_was_set_ = true;
59 786 pthread_cond_broadcast(&object_set_);
60 786 }
61
62 /**
63 * Retrieves the wrapped value object. If the value is not yet available it
64 * will automatically block until a different thread calls Set().
65 * @return the containing value object
66 */
67 786 T &Get() {
68 786 Wait();
69 786 return object_;
70 }
71
72 const T &Get() const {
73 Wait();
74 return object_;
75 }
76
77 private:
78 786 void Wait() const {
79 786 MutexLockGuard guard(mutex_);
80
2/2
✓ Branch 0 taken 492 times.
✓ Branch 1 taken 786 times.
1278 while (!object_was_set_) {
81
1/2
✓ Branch 1 taken 492 times.
✗ Branch 2 not taken.
492 pthread_cond_wait(&object_set_, &mutex_);
82 }
83 786 }
84
85 T object_;
86 mutable pthread_mutex_t mutex_;
87 mutable pthread_cond_t object_set_;
88 bool object_was_set_;
89 };
90
91 #ifdef CVMFS_NAMESPACE_GUARD
92 } // namespace CVMFS_NAMESPACE_GUARD
93 #endif
94
95 #endif // CVMFS_UTIL_FUTURE_H_
96