/usr/include/hphp/util/synchronizable-multi.h is in hhvm-dev 3.21.0+dfsg-2ubuntu2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | /*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_SYNCHRONIZABLE_MULTI_H_
#define incl_HPHP_SYNCHRONIZABLE_MULTI_H_
#include "hphp/util/mutex.h"
#include <pthread.h>
#include <folly/IntrusiveList.h>
#include <vector>
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
/**
* A Synchronizable object that has multiple conditional variables. The benefit
* is, notify() can choose to wake up a thread that is more favorable (e.g.,
* one with stack/heap mapped on huge pages, or one that is recently active).
*/
struct SynchronizableMulti {
explicit SynchronizableMulti(int size);
virtual ~SynchronizableMulti() {}
/*
* Threads are notified based on their priority. The priority is decided when
* calling wait().
*/
enum Priority {
High,
Middle,
Low
};
/**
* "id" is an arbitrary number that locates the conditional variable to wait
* on.
*/
void wait(int id, int q, Priority pri);
bool wait(int id, int q, Priority pri, long seconds); // false if timed out
bool wait(int id, int q, Priority pri, long seconds, long long nanosecs);
void notify();
void notifyAll();
void setNumGroups(int num_groups);
Mutex &getMutex() { return m_mutex;}
private:
Mutex m_mutex;
int m_group;
struct alignas(64) CondVarNode {
pthread_cond_t m_cond;
folly::IntrusiveListHook m_listHook;
CondVarNode() {
pthread_cond_init(&m_cond, nullptr);
}
~CondVarNode() {
pthread_cond_destroy(&m_cond);
}
/* implicit */ operator pthread_cond_t*() {
return &m_cond;
}
void unlink() {
if (m_listHook.is_linked()) m_listHook.unlink();
}
};
std::vector<CondVarNode> m_conds;
// List with push_middle, to support three priorities. It is implemented
// using two intrusive lists.
struct alignas(64) CondVarList {
CondVarList() = default;
bool empty() const {
return m_highPriList.empty() && m_midLowPriList.empty();
}
CondVarNode& front() {
if (!m_highPriList.empty()) return m_highPriList.front();
return m_midLowPriList.front();
}
void pop_front() {
if (!m_highPriList.empty()) m_highPriList.pop_front();
else m_midLowPriList.pop_front();
}
void push_front(CondVarNode& c) {
c.unlink();
m_highPriList.push_front(c);
}
void push_middle(CondVarNode& c) {
c.unlink();
m_midLowPriList.push_front(c);
}
void push_back(CondVarNode& c) {
c.unlink();
m_midLowPriList.push_back(c);
}
private:
using CondVarIList =
folly::IntrusiveList<CondVarNode, &CondVarNode::m_listHook>;
CondVarIList m_highPriList;
CondVarIList m_midLowPriList;
};
std::vector<CondVarList> m_cond_list_vec;
bool waitImpl(int id, int q, Priority pri, timespec *ts);
};
///////////////////////////////////////////////////////////////////////////////
}
#endif // incl_HPHP_SYNCHRONIZABLE_MULTI_H_
|