Kea  1.9.9-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 
208 public:
209 
211  struct ParkingInfo {
213  boost::any parked_object_;
214 
216  std::function<void()> unpark_callback_;
217 
220 
224  ParkingInfo() : refcount_(0) {}
225 
230  ParkingInfo(const boost::any& parked_object,
231  std::function<void()> callback = 0)
232  : parked_object_(parked_object), unpark_callback_(callback),
233  refcount_(0) {}
234 
239  void update(const boost::any& parked_object,
240  std::function<void()> callback) {
241  parked_object_ = parked_object;
242  unpark_callback_ = callback;
243  }
244  };
245 
246 private:
247 
249  typedef std::unordered_map<std::string, ParkingInfo> ParkingInfoList;
250 
252  typedef ParkingInfoList::iterator ParkingInfoListIterator;
253 
255  ParkingInfoList parking_;
256 
262  template<typename T>
263  std::string makeKey(T parked_object) {
264  std::stringstream ss;
265  ss << boost::any_cast<T>(parked_object);
266  return (ss.str());
267  }
268 
275  template<typename T>
276  ParkingInfoListIterator find(T parked_object) {
277  return (parking_.find(makeKey(parked_object)));
278  }
279 
284  std::mutex mutex_;
285 };
286 
288 typedef boost::shared_ptr<ParkingLot> ParkingLotPtr;
289 
301 public:
302 
307  ParkingLotHandle(const ParkingLotPtr& parking_lot)
308  : parking_lot_(parking_lot) {
309  }
310 
320  template<typename T>
321  int reference(T parked_object) {
322  return (parking_lot_->reference(parked_object));
323  }
324 
333  template<typename T>
334  int dereference(T parked_object) {
335  return (parking_lot_->dereference(parked_object));
336  }
337 
349  template<typename T>
350  bool unpark(T parked_object) {
351  return (parking_lot_->unpark(parked_object));
352  }
353 
362  template<typename T>
363  bool drop(T parked_object) {
364  return (parking_lot_->drop(parked_object));
365  }
366 
367 private:
368 
370  ParkingLotPtr parking_lot_;
371 
372 };
373 
375 typedef boost::shared_ptr<ParkingLotHandle> ParkingLotHandlePtr;
376 
378 class ParkingLots {
379 public:
380 
384  void clear() {
385  std::lock_guard<std::mutex> lock(mutex_);
386  parking_lots_.clear();
387  }
388 
397  ParkingLotPtr getParkingLotPtr(const int hook_index) {
398  std::lock_guard<std::mutex> lock(mutex_);
399  if (parking_lots_.count(hook_index) == 0) {
400  parking_lots_[hook_index] = boost::make_shared<ParkingLot>();
401  }
402  return (parking_lots_[hook_index]);
403  }
404 
405 private:
406 
408  std::unordered_map<int, ParkingLotPtr> parking_lots_;
409 
411  std::mutex mutex_;
412 };
413 
415 typedef boost::shared_ptr<ParkingLots> ParkingLotsPtr;
416 
417 } // end of namespace hooks
418 } // end of namespace isc
419 
420 #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:300
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:288
Holds information about parked object.
Definition: parking_lots.h:211
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:384
void update(const boost::any &parked_object, std::function< void()> callback)
Update parking information.
Definition: parking_lots.h:239
int dereference(T parked_object)
Decreases the reference counter for the parked object.
Definition: parking_lots.h:334
#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:307
int reference(T parked_object)
Increases reference counter for the parked object.
Definition: parking_lots.h:321
Collection of parking lots for various hook points.
Definition: parking_lots.h:378
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:415
Defines the logger used by the top-level component of kea-dhcp-ddns.
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:363
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:216
boost::shared_ptr< ParkingLotHandle > ParkingLotHandlePtr
Pointer to the parking lot handle.
Definition: parking_lots.h:375
ParkingLotPtr getParkingLotPtr(const int hook_index)
Returns pointer to the parking lot for a hook points.
Definition: parking_lots.h:397
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:230
boost::any parked_object_
The parked object.
Definition: parking_lots.h:213
bool unpark(T parked_object)
Signals that the object should be unparked.
Definition: parking_lots.h:350
int refcount_
The current reference count.
Definition: parking_lots.h:219