Welcome to mirror list, hosted at ThFree Co, Russian Federation.

fence_manager.cpp « base - github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: bae6a7884a372c04a5c3bb1a38494ce51e09e7d2 (plain)
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
128
129
130
131
132
133
#include "fence_manager.hpp"

#include "../base/assert.hpp"
#include "../base/logging.hpp"

FenceManager::FenceManager(int conditionPoolSize)
  : m_currentFence(0),
    m_isCancelled(false)
{
  for (unsigned i = 0; i < conditionPoolSize; ++i)
    m_conditionPool.push_back(new threads::Condition());
}

FenceManager::~FenceManager()
{
  for (map<int, threads::Condition*>::const_iterator it = m_activeFences.begin();
       it != m_activeFences.end();
       ++it)
  {
    it->second->Signal();
    delete it->second;
  }

  for (list<threads::Condition*>::iterator it = m_conditionPool.begin(); it != m_conditionPool.end(); ++it)
    delete *it;
}

int FenceManager::insertFence()
{
  threads::MutexGuard g(m_mutex);

  if (m_isCancelled)
    return -1;

  if (m_conditionPool.empty())
    return -1;

  threads::Condition * cond = m_conditionPool.front();
  m_conditionPool.pop_front();

  int id = m_currentFence++;

  m_activeFences[id] = cond;

  return id;
}

void FenceManager::signalFence(int id)
{
  threads::MutexGuard mutexGuard(m_mutex);

  if (m_isCancelled)
    return;

  map<int, threads::Condition*>::iterator it = m_activeFences.find(id);

  if (it == m_activeFences.end())
  {
    LOG(LINFO, ("fence with id", id, "has been already signalled or hasn't been installed yet"));
    return;
  }

  threads::Condition * cond = it->second;

  /// i suppose that this guard will be destroyed after mutexGuard
  threads::ConditionGuard fenceGuard(*cond);

  /// erasing fence from active fences
  m_activeFences.erase(it);

  /// returning condition to the pool
  m_conditionPool.push_back(cond);

  /// signalling to all waiting fences
  fenceGuard.Signal(true);
}

void FenceManager::joinFence(int id)
{
  threads::Condition * cond = 0;
  {
    threads::MutexGuard g(m_mutex);

    if (m_isCancelled)
      return;

    map<int, threads::Condition*>::iterator it = m_activeFences.find(id);

    if (it == m_activeFences.end())
    {
      LOG(LINFO, ("fence with id", id, "has been already reached in the past or hasn't been installed yet"));
      return;
    }

    cond = it->second;

    /// we should lock condition here, to prevent us from the situation
    /// when the condition will be signaled before it's been waited for
    cond->Lock();
  }

  /// to prevent from "spurious wakeups"
  while (m_activeFences.find(id) != m_activeFences.end())
    cond->Wait();

  cond->Unlock();
}

void FenceManager::cancel()
{
  threads::MutexGuard g(m_mutex);

  if (m_isCancelled)
    return;

  m_isCancelled = true;

  list<pair<int, threads::Condition*> > tempList;

  for (map<int, threads::Condition*>::iterator it = m_activeFences.begin();
       it != m_activeFences.end();
       ++it)
       tempList.push_back(make_pair(it->first, it->second));

  for (list<pair<int, threads::Condition*> >::const_iterator it = tempList.begin();
       it != tempList.end();
       ++it)
  {
    threads::ConditionGuard fenceGuard(*it->second);
    m_activeFences.erase(it->first);
    fenceGuard.Signal(true);
  }
}