include: fixup header inclusion
[c11tester.git] / promise.cc
1 #define __STDC_FORMAT_MACROS
2 #include <inttypes.h>
3
4 #include "promise.h"
5 #include "model.h"
6 #include "schedule.h"
7 #include "action.h"
8 #include "threads-model.h"
9
10 /**
11  * @brief Promise constructor
12  * @param read The read which reads from a promised future value
13  * @param fv The future value that is promised
14  */
15 Promise::Promise(ModelAction *read, struct future_value fv) :
16         num_available_threads(0),
17         value(fv.value),
18         expiration(fv.expiration),
19         read(read),
20         write(NULL)
21 {
22         add_thread(fv.tid);
23         eliminate_thread(read->get_tid());
24 }
25
26 /**
27  * Eliminate a thread which no longer can satisfy this promise. Once all
28  * enabled threads have been eliminated, this promise is unresolvable.
29  *
30  * @param tid The thread ID of the thread to eliminate
31  * @return True, if this elimination has invalidated the promise; false
32  * otherwise
33  */
34 bool Promise::eliminate_thread(thread_id_t tid)
35 {
36         unsigned int id = id_to_int(tid);
37         if (!thread_is_available(tid))
38                 return false;
39
40         available_thread[id] = false;
41         num_available_threads--;
42         return has_failed();
43 }
44
45 /**
46  * Add a thread which may resolve this promise
47  *
48  * @param tid The thread ID
49  */
50 void Promise::add_thread(thread_id_t tid)
51 {
52         unsigned int id = id_to_int(tid);
53         if (id >= available_thread.size())
54                 available_thread.resize(id + 1, false);
55         if (!available_thread[id]) {
56                 available_thread[id] = true;
57                 num_available_threads++;
58         }
59 }
60
61 /**
62  * Check if a thread is available for resolving this promise. That is, the
63  * thread must have been previously marked for resolving this promise, and it
64  * cannot have been eliminated due to synchronization, etc.
65  *
66  * @param tid Thread ID of the thread to check
67  * @return True if the thread is available; false otherwise
68  */
69 bool Promise::thread_is_available(thread_id_t tid) const
70 {
71         unsigned int id = id_to_int(tid);
72         if (id >= available_thread.size())
73                 return false;
74         return available_thread[id];
75 }
76
77 /** @brief Print debug info about the Promise */
78 void Promise::print() const
79 {
80         model_print("Promised value %#" PRIx64 ", read from thread %d, available threads to resolve: ", value, id_to_int(read->get_tid()));
81         for (unsigned int i = 0; i < available_thread.size(); i++)
82                 if (available_thread[i])
83                         model_print("[%d]", i);
84         model_print("\n");
85 }
86
87 /**
88  * Check if this promise has failed. A promise can fail when all threads which
89  * could possibly satisfy the promise have been eliminated.
90  *
91  * @return True, if this promise has failed; false otherwise
92  */
93 bool Promise::has_failed() const
94 {
95         return num_available_threads == 0;
96 }
97
98 /**
99  * @brief Check if an action's thread and location are compatible for resolving
100  * this promise
101  * @param act The action to check against
102  * @return True if we are compatible; false otherwise
103  */
104 bool Promise::is_compatible(const ModelAction *act) const
105 {
106         return thread_is_available(act->get_tid()) && read->same_var(act);
107 }
108
109 /**
110  * @brief Check if an action's thread and location are compatible for resolving
111  * this promise, and that the promise is thread-exclusive
112  * @param act The action to check against
113  * @return True if we are compatible and exclusive; false otherwise
114  */
115 bool Promise::is_compatible_exclusive(const ModelAction *act) const
116 {
117         return get_num_available_threads() == 1 && is_compatible(act);
118 }