Kea 2.7.5
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
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
23namespace isc {
24namespace hooks {
25
74public:
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
214public:
215
217 struct ParkingInfo {
219 boost::any parked_object_;
220
222 std::function<void()> unpark_callback_;
223
226
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
252private:
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
294typedef boost::shared_ptr<ParkingLot> ParkingLotPtr;
295
307public:
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
373private:
374
376 ParkingLotPtr parking_lot_;
377
378};
379
381typedef boost::shared_ptr<ParkingLotHandle> ParkingLotHandlePtr;
382
385public:
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
411private:
412
414 std::unordered_map<int, ParkingLotPtr> parking_lots_;
415
417 std::mutex mutex_;
418};
419
421typedef boost::shared_ptr<ParkingLots> ParkingLotsPtr;
422
423} // end of namespace hooks
424} // end of namespace isc
425
426#endif
A generic exception that is thrown if a function is called in a prohibited way.
Provides a limited view to the ParkingLot.
bool drop(T parked_object)
Removes parked object without calling a callback.
bool unpark(T parked_object)
Signals that the object should be unparked.
int reference(T parked_object)
Increases reference counter for the parked object.
int dereference(T parked_object)
Decreases the reference counter for the parked object.
ParkingLotHandle(const ParkingLotPtr &parking_lot)
Constructor.
Parking lot for objects, e.g.
bool unpark(T parked_object, bool force=false)
Signals that the object should be unparked.
bool drop(T parked_object)
Removes parked object without calling a callback.
size_t size()
Returns the current number of objects.
int dereference(T parked_object)
Decreases the reference counter for the parked object.
int reference(T parked_object)
Increases reference counter for the parked object.
void park(T parked_object, std::function< void()> unpark_callback)
Parks an object.
Collection of parking lots for various hook points.
ParkingLotPtr getParkingLotPtr(const int hook_index)
Returns pointer to the parking lot for a hook points.
void clear()
Removes all parked objects.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< ParkingLots > ParkingLotsPtr
Type of the pointer to the parking lots.
boost::shared_ptr< ParkingLotHandle > ParkingLotHandlePtr
Pointer to the parking lot handle.
boost::shared_ptr< ParkingLot > ParkingLotPtr
Type of the pointer to the parking lot.
Defines the logger used by the top-level component of kea-lfc.
Holds information about parked object.
int refcount_
The current reference count.
boost::any parked_object_
The parked object.
void update(const boost::any &parked_object, std::function< void()> callback)
Update parking information.
ParkingInfo(const boost::any &parked_object, std::function< void()> callback=0)
Constructor.
std::function< void()> unpark_callback_
The pointer to callback.