17ec681f3Smrg// 27ec681f3Smrg// Copyright 2013 Francisco Jerez 37ec681f3Smrg// 47ec681f3Smrg// Permission is hereby granted, free of charge, to any person obtaining a 57ec681f3Smrg// copy of this software and associated documentation files (the "Software"), 67ec681f3Smrg// to deal in the Software without restriction, including without limitation 77ec681f3Smrg// the rights to use, copy, modify, merge, publish, distribute, sublicense, 87ec681f3Smrg// and/or sell copies of the Software, and to permit persons to whom the 97ec681f3Smrg// Software is furnished to do so, subject to the following conditions: 107ec681f3Smrg// 117ec681f3Smrg// The above copyright notice and this permission notice shall be included in 127ec681f3Smrg// all copies or substantial portions of the Software. 137ec681f3Smrg// 147ec681f3Smrg// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 157ec681f3Smrg// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 167ec681f3Smrg// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 177ec681f3Smrg// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 187ec681f3Smrg// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 197ec681f3Smrg// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 207ec681f3Smrg// OTHER DEALINGS IN THE SOFTWARE. 217ec681f3Smrg// 227ec681f3Smrg 237ec681f3Smrg#ifndef CLOVER_UTIL_POINTER_HPP 247ec681f3Smrg#define CLOVER_UTIL_POINTER_HPP 257ec681f3Smrg 267ec681f3Smrg#include <atomic> 277ec681f3Smrg 287ec681f3Smrgnamespace clover { 297ec681f3Smrg /// 307ec681f3Smrg /// Some helper functions for raw pointer operations 317ec681f3Smrg /// 327ec681f3Smrg template <class T> 337ec681f3Smrg static bool 347ec681f3Smrg ptr_is_aligned(const T *ptr, uintptr_t a) noexcept { 357ec681f3Smrg assert(a == (a & -a)); 367ec681f3Smrg uintptr_t ptr_value = reinterpret_cast<uintptr_t>(ptr); 377ec681f3Smrg return (ptr_value & (a - 1)) == 0; 387ec681f3Smrg } 397ec681f3Smrg 407ec681f3Smrg /// 417ec681f3Smrg /// Base class for objects that support reference counting. 427ec681f3Smrg /// 437ec681f3Smrg class ref_counter { 447ec681f3Smrg public: 457ec681f3Smrg ref_counter(unsigned value = 1) : _ref_count(value) {} 467ec681f3Smrg 477ec681f3Smrg unsigned 487ec681f3Smrg ref_count() const { 497ec681f3Smrg return _ref_count; 507ec681f3Smrg } 517ec681f3Smrg 527ec681f3Smrg void 537ec681f3Smrg retain() { 547ec681f3Smrg _ref_count++; 557ec681f3Smrg } 567ec681f3Smrg 577ec681f3Smrg bool 587ec681f3Smrg release() { 597ec681f3Smrg return (--_ref_count) == 0; 607ec681f3Smrg } 617ec681f3Smrg 627ec681f3Smrg private: 637ec681f3Smrg std::atomic<unsigned> _ref_count; 647ec681f3Smrg }; 657ec681f3Smrg 667ec681f3Smrg /// 677ec681f3Smrg /// Simple reference to a clover::ref_counter object. Unlike 687ec681f3Smrg /// clover::intrusive_ptr and clover::intrusive_ref, it does nothing 697ec681f3Smrg /// special when the reference count drops to zero. 707ec681f3Smrg /// 717ec681f3Smrg class ref_holder { 727ec681f3Smrg public: 737ec681f3Smrg ref_holder(ref_counter &o) : p(&o) { 747ec681f3Smrg p->retain(); 757ec681f3Smrg } 767ec681f3Smrg 777ec681f3Smrg ref_holder(const ref_holder &ref) : 787ec681f3Smrg ref_holder(*ref.p) { 797ec681f3Smrg } 807ec681f3Smrg 817ec681f3Smrg ref_holder(ref_holder &&ref) : 827ec681f3Smrg p(ref.p) { 837ec681f3Smrg ref.p = NULL; 847ec681f3Smrg } 857ec681f3Smrg 867ec681f3Smrg ~ref_holder() { 877ec681f3Smrg if (p) 887ec681f3Smrg p->release(); 897ec681f3Smrg } 907ec681f3Smrg 917ec681f3Smrg ref_holder & 927ec681f3Smrg operator=(ref_holder ref) { 937ec681f3Smrg std::swap(ref.p, p); 947ec681f3Smrg return *this; 957ec681f3Smrg } 967ec681f3Smrg 977ec681f3Smrg bool 987ec681f3Smrg operator==(const ref_holder &ref) const { 997ec681f3Smrg return p == ref.p; 1007ec681f3Smrg } 1017ec681f3Smrg 1027ec681f3Smrg bool 1037ec681f3Smrg operator!=(const ref_holder &ref) const { 1047ec681f3Smrg return p != ref.p; 1057ec681f3Smrg } 1067ec681f3Smrg 1077ec681f3Smrg private: 1087ec681f3Smrg ref_counter *p; 1097ec681f3Smrg }; 1107ec681f3Smrg 1117ec681f3Smrg /// 1127ec681f3Smrg /// Intrusive smart pointer for objects that implement the 1137ec681f3Smrg /// clover::ref_counter interface. 1147ec681f3Smrg /// 1157ec681f3Smrg template<typename T> 1167ec681f3Smrg class intrusive_ptr { 1177ec681f3Smrg public: 1187ec681f3Smrg intrusive_ptr(T *q = NULL) : p(q) { 1197ec681f3Smrg if (p) 1207ec681f3Smrg p->retain(); 1217ec681f3Smrg } 1227ec681f3Smrg 1237ec681f3Smrg intrusive_ptr(const intrusive_ptr &ptr) : 1247ec681f3Smrg intrusive_ptr(ptr.p) { 1257ec681f3Smrg } 1267ec681f3Smrg 1277ec681f3Smrg intrusive_ptr(intrusive_ptr &&ptr) : 1287ec681f3Smrg p(ptr.p) { 1297ec681f3Smrg ptr.p = NULL; 1307ec681f3Smrg } 1317ec681f3Smrg 1327ec681f3Smrg ~intrusive_ptr() { 1337ec681f3Smrg if (p && p->release()) 1347ec681f3Smrg delete p; 1357ec681f3Smrg } 1367ec681f3Smrg 1377ec681f3Smrg intrusive_ptr & 1387ec681f3Smrg operator=(intrusive_ptr ptr) { 1397ec681f3Smrg std::swap(ptr.p, p); 1407ec681f3Smrg return *this; 1417ec681f3Smrg } 1427ec681f3Smrg 1437ec681f3Smrg bool 1447ec681f3Smrg operator==(const intrusive_ptr &ref) const { 1457ec681f3Smrg return p == ref.p; 1467ec681f3Smrg } 1477ec681f3Smrg 1487ec681f3Smrg bool 1497ec681f3Smrg operator!=(const intrusive_ptr &ref) const { 1507ec681f3Smrg return p != ref.p; 1517ec681f3Smrg } 1527ec681f3Smrg 1537ec681f3Smrg T & 1547ec681f3Smrg operator*() const { 1557ec681f3Smrg return *p; 1567ec681f3Smrg } 1577ec681f3Smrg 1587ec681f3Smrg T * 1597ec681f3Smrg operator->() const { 1607ec681f3Smrg return p; 1617ec681f3Smrg } 1627ec681f3Smrg 1637ec681f3Smrg T * 1647ec681f3Smrg operator()() const { 1657ec681f3Smrg return p; 1667ec681f3Smrg } 1677ec681f3Smrg 1687ec681f3Smrg explicit operator bool() const { 1697ec681f3Smrg return p; 1707ec681f3Smrg } 1717ec681f3Smrg 1727ec681f3Smrg explicit operator T *() const { 1737ec681f3Smrg return p; 1747ec681f3Smrg } 1757ec681f3Smrg 1767ec681f3Smrg private: 1777ec681f3Smrg T *p; 1787ec681f3Smrg }; 1797ec681f3Smrg 1807ec681f3Smrg /// 1817ec681f3Smrg /// Intrusive smart reference for objects that implement the 1827ec681f3Smrg /// clover::ref_counter interface. 1837ec681f3Smrg /// 1847ec681f3Smrg template<typename T> 1857ec681f3Smrg class intrusive_ref { 1867ec681f3Smrg public: 1877ec681f3Smrg intrusive_ref(T &o) : p(&o) { 1887ec681f3Smrg p->retain(); 1897ec681f3Smrg } 1907ec681f3Smrg 1917ec681f3Smrg intrusive_ref(const intrusive_ref &ref) : 1927ec681f3Smrg intrusive_ref(*ref.p) { 1937ec681f3Smrg } 1947ec681f3Smrg 1957ec681f3Smrg intrusive_ref(intrusive_ref &&ref) : 1967ec681f3Smrg p(ref.p) { 1977ec681f3Smrg ref.p = NULL; 1987ec681f3Smrg } 1997ec681f3Smrg 2007ec681f3Smrg ~intrusive_ref() { 2017ec681f3Smrg if (p && p->release()) 2027ec681f3Smrg delete p; 2037ec681f3Smrg } 2047ec681f3Smrg 2057ec681f3Smrg intrusive_ref & 2067ec681f3Smrg operator=(intrusive_ref ref) { 2077ec681f3Smrg std::swap(ref.p, p); 2087ec681f3Smrg return *this; 2097ec681f3Smrg } 2107ec681f3Smrg 2117ec681f3Smrg bool 2127ec681f3Smrg operator==(const intrusive_ref &ref) const { 2137ec681f3Smrg return p == ref.p; 2147ec681f3Smrg } 2157ec681f3Smrg 2167ec681f3Smrg bool 2177ec681f3Smrg operator!=(const intrusive_ref &ref) const { 2187ec681f3Smrg return p != ref.p; 2197ec681f3Smrg } 2207ec681f3Smrg 2217ec681f3Smrg T & 2227ec681f3Smrg operator()() const { 2237ec681f3Smrg return *p; 2247ec681f3Smrg } 2257ec681f3Smrg 2267ec681f3Smrg operator T &() const { 2277ec681f3Smrg return *p; 2287ec681f3Smrg } 2297ec681f3Smrg 2307ec681f3Smrg private: 2317ec681f3Smrg T *p; 2327ec681f3Smrg }; 2337ec681f3Smrg 2347ec681f3Smrg /// 2357ec681f3Smrg /// Initialize a clover::intrusive_ref from a newly created object 2367ec681f3Smrg /// using the specified constructor arguments. 2377ec681f3Smrg /// 2387ec681f3Smrg template<typename T, typename... As> 2397ec681f3Smrg intrusive_ref<T> 2407ec681f3Smrg create(As &&... as) { 2417ec681f3Smrg intrusive_ref<T> ref { *new T(std::forward<As>(as)...) }; 2427ec681f3Smrg ref().release(); 2437ec681f3Smrg return ref; 2447ec681f3Smrg } 2457ec681f3Smrg 2467ec681f3Smrg /// 2477ec681f3Smrg /// Class that implements the usual pointer interface but in fact 2487ec681f3Smrg /// contains the object it seems to be pointing to. 2497ec681f3Smrg /// 2507ec681f3Smrg template<typename T> 2517ec681f3Smrg class pseudo_ptr { 2527ec681f3Smrg public: 2537ec681f3Smrg pseudo_ptr(T x) : x(x) { 2547ec681f3Smrg } 2557ec681f3Smrg 2567ec681f3Smrg pseudo_ptr(const pseudo_ptr &p) : x(p.x) { 2577ec681f3Smrg } 2587ec681f3Smrg 2597ec681f3Smrg pseudo_ptr & 2607ec681f3Smrg operator=(const pseudo_ptr &p) { 2617ec681f3Smrg x = p.x; 2627ec681f3Smrg return *this; 2637ec681f3Smrg } 2647ec681f3Smrg 2657ec681f3Smrg T & 2667ec681f3Smrg operator*() { 2677ec681f3Smrg return x; 2687ec681f3Smrg } 2697ec681f3Smrg 2707ec681f3Smrg T * 2717ec681f3Smrg operator->() { 2727ec681f3Smrg return &x; 2737ec681f3Smrg } 2747ec681f3Smrg 2757ec681f3Smrg explicit operator bool() const { 2767ec681f3Smrg return true; 2777ec681f3Smrg } 2787ec681f3Smrg 2797ec681f3Smrg private: 2807ec681f3Smrg T x; 2817ec681f3Smrg }; 2827ec681f3Smrg} 2837ec681f3Smrg 2847ec681f3Smrg#endif 285