Kea  2.3.1-git
parking_lots.h
Go to the documentation of this file.
1 // Copyright (C) 2018-2021 Internet Systems Consortium, Inc. ("ISC")
2 //
3 // This Source Code Form is subject to the terms of the Mozilla Public
4 // License, v. 2.0. If a copy of the MPL was not distributed with this
5 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 
7 #ifndef PARKING_LOTS_H
8 #define PARKING_LOTS_H
9 
10 #include <exceptions/exceptions.h>
11 #include <boost/any.hpp>
12 #include <boost/make_shared.hpp>
13 #include <boost/shared_ptr.hpp>
14 
15 #include <functional>
16 #include <iostream>
17 #include <sstream>
18 #include <list>
19 #include <unordered_map>
20 #include <mutex>
21 #include <thread>
22 
23 namespace isc {
24 namespace hooks {
25 
73 class ParkingLot {
74 public:
82  template<typename T>
83  void park(T parked_object, std::function<void()> unpark_callback) {
84  std::lock_guard<std::mutex> lock(mutex_);
85  auto it = find(parked_object);
86  if (it != parking_.end()) {
87  isc_throw(InvalidOperation, "object is already parked!");
88  }
89 
90  // Add the object to the parking lot. At this point refcount = 0.
91  ParkingInfo pinfo(parked_object, unpark_callback);
92  parking_[makeKey(parked_object)] = pinfo;
93  }
94 
104  template<typename T>
105  int reference(T parked_object) {
106  std::lock_guard<std::mutex> lock(mutex_);
107  auto it = find(parked_object);
108  if (it == parking_.end()) {
109  isc_throw(InvalidOperation, "cannot reference an object"
110  " that has not been parked.");
111  }
112 
113  // Bump and return the reference count
114  return (++it->second.refcount_);
115  }
116 
125  template<typename T>
126  int dereference(T parked_object) {
127  std::lock_guard<std::mutex> lock(mutex_);
128  auto it = find(parked_object);
129  if (it == parking_.end()) {
130  isc_throw(InvalidOperation, "cannot dereference an object"
131  " that has not been parked.");
132  }
133 
134  // Decrement and return the reference count.
135  return (--it->second.refcount_);
136  }
137 
151  template<typename T>
152  bool unpark(T parked_object, bool force = false) {
153  // Initialize as the empty function.
154  std::function<void()> cb;
155  {
156  std::lock_guard<std::mutex> lock(mutex_);
157  auto it = find(parked_object);
158  if (it == parking_.end()) {
159  // No such parked object.
160  return (false);
161  }
162 
163  if (force) {
164  it->second.refcount_ = 0;
165  } else {
166  --it->second.refcount_;
167  }
168 
169  if (it->second.refcount_ <= 0) {
170  // Unpark the packet and set the callback.
171  cb = it->second.unpark_callback_;
172  parking_.erase(it);
173  }
174  }
175 
176  // Invoke the callback if not empty.
177  if (cb) {
178  cb();
179  }
180 
181  // Parked object found, so return true to indicate that the
182  // operation was successful. It doesn't necessarily mean
183  // that the object was unparked, but at least the reference
184  // count was decreased.
185  return (true);
186  }
187 
194  template<typename T>
195  bool drop(T parked_object) {
196  std::lock_guard<std::mutex> lock(mutex_);
197  auto it = find(parked_object);
198  if (it != parking_.end()) {
199  // Parked object found.
200  parking_.erase(it);
201  return (true);
202  }
203 
204  // No such object.
205  return (false);
206  }
207 
209  size_t size() {
210  std::lock_guard<std::mutex> lock(mutex_);
211  return (parking_.size());
212  }
213 
214 public:
215 
217  struct ParkingInfo {
219  boost::any parked_object_;
220 
222  std::function<void()> unpark_callback_;
223 
226 
230  ParkingInfo() : refcount_(0) {}
231 
236  ParkingInfo(const boost::any& parked_object,
237  std::function<void()> callback = 0)
238  : parked_object_(parked_object), unpark_callback_(callback),
239  refcount_(0) {}
240 
245  void update(const boost::any& parked_object,
246  std::function<void()> callback) {
247  parked_object_ = parked_object;
248  unpark_callback_ = callback;
249  }
250  };
251 
252 private:
253 
255  typedef std::unordered_map<std::string, ParkingInfo> ParkingInfoList;
256 
258  typedef ParkingInfoList::iterator ParkingInfoListIterator;
259 
261  ParkingInfoList parking_;
262 
268  template<typename T>
269  std::string makeKey(T parked_object) {
270  std::stringstream ss;
271  ss << boost::any_cast<T>(parked_object);
272  return (ss.str());
273  }
274 
281  template<typename T>
282  ParkingInfoListIterator find(T parked_object) {
283  return (parking_.find(makeKey(parked_object)));
284  }
285 
290  std::mutex mutex_;
291 };
292 
294 typedef boost::shared_ptr<ParkingLot> ParkingLotPtr;
295 
307 public:
308 
313  ParkingLotHandle(const ParkingLotPtr& parking_lot)
314  : parking_lot_(parking_lot) {
315  }
316 
326  template<typename T>
327  int reference(T parked_object) {
328  return (parking_lot_->reference(parked_object));
329  }
330 
339  template<typename T>
340  int dereference(T parked_object) {
341  return (parking_lot_->dereference(parked_object));
342  }
343 
355  template<typename T>
356  bool unpark(T parked_object) {
357  return (parking_lot_->unpark(parked_object));
358  }
359 
368  template<typename T>
369  bool drop(T parked_object) {
370  return (parking_lot_->drop(parked_object));
371  }
372 
373 private:
374 
376  ParkingLotPtr parking_lot_;
377 
378 };
379 
381 typedef boost::shared_ptr<ParkingLotHandle> ParkingLotHandlePtr;
382 
384 class ParkingLots {
385 public:
386 
390  void clear() {
391  std::lock_guard<std::mutex> lock(mutex_);
392  parking_lots_.clear();
393  }
394 
403  ParkingLotPtr getParkingLotPtr(const int hook_index) {
404  std::lock_guard<std::mutex> lock(mutex_);
405  if (parking_lots_.count(hook_index) == 0) {
406  parking_lots_[hook_index] = boost::make_shared<ParkingLot>();
407  }
408  return (parking_lots_[hook_index]);
409  }
410 
411 private:
412 
414  std::unordered_map<int, ParkingLotPtr> parking_lots_;
415 
417  std::mutex mutex_;
418 };
419 
421 typedef boost::shared_ptr<ParkingLots> ParkingLotsPtr;
422 
423 } // end of namespace hooks
424 } // end of namespace isc
425 
426 #endif
bool drop(T parked_object)
Removes parked object without calling a callback.
Definition: parking_lots.h:195
Provides a limited view to the ParkingLot.
Definition: parking_lots.h:306
int reference(T parked_object)
Increases reference counter for the parked object.
Definition: parking_lots.h:105
boost::shared_ptr< ParkingLot > ParkingLotPtr
Type of the pointer to the parking lot.
Definition: parking_lots.h:294
Holds information about parked object.
Definition: parking_lots.h:217
void park(T parked_object, std::function< void()> unpark_callback)
Parks an object.
Definition: parking_lots.h:83
void clear()
Removes all parked objects.
Definition: parking_lots.h:390
void update(const boost::any &parked_object, std::function< void()> callback)
Update parking information.
Definition: parking_lots.h:245
int dereference(T parked_object)
Decreases the reference counter for the parked object.
Definition: parking_lots.h:340
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
ParkingLotHandle(const ParkingLotPtr &parking_lot)
Constructor.
Definition: parking_lots.h:313
int reference(T parked_object)
Increases reference counter for the parked object.
Definition: parking_lots.h:327
Collection of parking lots for various hook points.
Definition: parking_lots.h:384
Parking lot for objects, e.g.
Definition: parking_lots.h:73
boost::shared_ptr< ParkingLots > ParkingLotsPtr
Type of the pointer to the parking lots.
Definition: parking_lots.h:421
Defines the logger used by the top-level component of kea-lfc.
int dereference(T parked_object)
Decreases the reference counter for the parked object.
Definition: parking_lots.h:126
bool drop(T parked_object)
Removes parked object without calling a callback.
Definition: parking_lots.h:369
A generic exception that is thrown if a function is called in a prohibited way.
std::function< void()> unpark_callback_
The pointer to callback.
Definition: parking_lots.h:222
boost::shared_ptr< ParkingLotHandle > ParkingLotHandlePtr
Pointer to the parking lot handle.
Definition: parking_lots.h:381
ParkingLotPtr getParkingLotPtr(const int hook_index)
Returns pointer to the parking lot for a hook points.
Definition: parking_lots.h:403
bool unpark(T parked_object, bool force=false)
Signals that the object should be unparked.
Definition: parking_lots.h:152
ParkingInfo(const boost::any &parked_object, std::function< void()> callback=0)
Constructor.
Definition: parking_lots.h:236
boost::any parked_object_
The parked object.
Definition: parking_lots.h:219
bool unpark(T parked_object)
Signals that the object should be unparked.
Definition: parking_lots.h:356
int refcount_
The current reference count.
Definition: parking_lots.h:225
size_t size()
Returns the current number of objects.
Definition: parking_lots.h:209