Main Page · Modules · All Classes · Class Hierarchy
MAContainerLocker.cpp
1 /*
2  * This file is part of the AiBO+ project
3  *
4  * Copyright (C) 2005-2016 Csaba Kertész (csaba.kertesz@gmail.com)
5  *
6  * AiBO+ is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * AiBO+ is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
19  *
20  */
21 
22 #include "MAContainerLocker.hpp"
23 
24 #include "MAContainerLockerPrivate.hpp"
25 
26 #include <MCLog.hpp>
27 #include <MCThreadLocalData.hpp>
28 
30 namespace
31 {
32 // Global container lock manager
33 MCThreadLocalData< MAContainerLockManager> ContainerLockManager(true);
34 
35 void CheckStaticContainerLockerVariables()
36 {
37  if (!ContainerLockManager.get())
38  {
39  ContainerLockManager.reset(new MAContainerLockManager);
40  }
41 }
42 }
43 
44 MAContainerLockManager::MAContainerLockManager() : ContainerDangerSignal(new ContainerDangerSignalType)
45 {
46 }
47 
48 
49 MAContainerLockManager& MAContainerLockManager::GetInstance()
50 {
51  CheckStaticContainerLockerVariables();
52  return *ContainerLockManager;
53 }
54 
55 
56 void MAContainerLockManager::RegisterFileName(const std::string& class_name, const std::string& file_name)
57 {
58  ClassFiles[class_name] = FormatFileString(file_name);
59 }
60 
61 
62 int MAContainerLockManager::RegisterContainer(const std::string& class_name, const std::string& container_name)
63 {
64  Containers.push_back(class_name+"::"+container_name);
65  return Containers.size()-1;
66 }
67 
68 
69 void MAContainerLockManager::Lock(int container_id, int line, const char* file_name)
70 {
71  const auto Iter = ContainerLocks.find(container_id);
72 
73  // Already locked
74  if (Iter != ContainerLocks.end())
75  {
76  std::string ContainerName = Containers[container_id];
77  std::string ClassName = ContainerName.substr(0, ContainerName.find_first_of(':'));
78  std::string OriginalFileName = Iter->second.second.empty() ? ClassFiles[ClassName] : Iter->second.second;
79  std::string CurrentFileName = file_name == nullptr ? ClassFiles[ClassName] : FormatFileString(std::string(file_name));
80 
81  MC_WARNING("Crash danger: The container %s has been locked at %s (line %d), cannot be locked at %s (line %d)",
82  Containers[container_id].c_str(), OriginalFileName.c_str(),
83  Iter->second.first, CurrentFileName.c_str(), line);
84  (*ContainerDangerSignal).Emit();
85  return;
86  }
87  MA::ContainerLockDescriptor Descriptor;
88 
89  Descriptor.first = line;
90  Descriptor.second = file_name == nullptr ? "" : FormatFileString(std::string(file_name));
91  ContainerLocks[container_id] = Descriptor;
92 }
93 
94 
95 void MAContainerLockManager::Unlock(int container_id, int line, const char* file_name)
96 {
97  std::string FileName = file_name == nullptr ? "" : FormatFileString(file_name);
98 
99  // Exact match is needed for removal
100  for (auto iter = ContainerLocks.begin(); iter != ContainerLocks.end(); ++iter)
101  {
102  if (iter->first == container_id && iter->second.first == line &&
103  iter->second.second == FileName)
104  {
105  ContainerLocks.erase(iter);
106  return;
107  }
108  }
109  // Not locked yet when the lock generated a warning already -> Return silently
110 }
111 
112 
113 std::string MAContainerLockManager::FormatFileString(const std::string& full_file_name) const
114 {
115  size_t Index = full_file_name.find_last_of('/');
116 
117  if (Index == std::string::npos)
118  {
119  return full_file_name;
120  }
121  return full_file_name.substr(Index+1, full_file_name.length()-Index);
122 }
123 
124 
125 int MAContainerLockManager::GetActiveLockNumber() const
126 {
127  return ContainerLocks.size();
128 }
130 
131 
132 MAContainerLocker::MAContainerLocker(const std::string& class_name, const std::string& file_name) :
133  ClassName(class_name)
134 {
135  CheckStaticContainerLockerVariables();
136  ContainerLockManager->RegisterFileName(ClassName, file_name);
137 }
138 
139 
140 int MAContainerLocker::RegisterContainer(const std::string& container_name)
141 {
142  CheckStaticContainerLockerVariables();
143  return ContainerLockManager->RegisterContainer(ClassName, container_name);
144 }
145 
146 
147 int MAContainerLocker::Lock(int container_id, int line, const char* file_name)
148 {
149  CheckStaticContainerLockerVariables();
150  ContainerLockManager->Lock(container_id, line, file_name);
151  return 0;
152 }
153 
154 
155 int MAContainerLocker::Unlock(int container_id, int line, const char* file_name)
156 {
157  CheckStaticContainerLockerVariables();
158  ContainerLockManager->Unlock(container_id, line, file_name);
159  return 1;
160 }
std::string ClassName
Class name.
#define MC_WARNING(...)
Warning macro.
Definition: MCLog.hpp:43
MAContainerLocker(const std::string &class_name, const std::string &file_name)
Class constructor.
int Lock(int container_id, int line, const char *file_name=nullptr)
Lock a container.
int Unlock(int container_id, int line, const char *file_name=nullptr)
Unlock a container.
int RegisterContainer(const std::string &container_name)
Register a container for locking.
A wrapper class to cover boost::thread_specific_ptr/folly::ThreadLocal API on certain targets...