/* Copyright (C) 2009-2013 Free Software Foundation, Inc. Contributed by Richard Henderson . This file is part of the GNU Transactional Memory Library (libitm). Libitm is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. Libitm is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Under Section 7 of GPL version 3, you are granted additional permissions described in the GCC Runtime Library Exception, version 3.1, as published by the Free Software Foundation. You should have received a copy of the GNU General Public License and a copy of the GCC Runtime Library Exception along with this program; see the files COPYING3 and COPYING.RUNTIME respectively. If not, see . */ /* Implements an AA tree (http://en.wikipedia.org/wiki/AA_tree) with an integer key, and data attached to the node via flexible array member. */ #ifndef LIBITM_AATREE_H #define LIBITM_AATREE_H 1 namespace GTM HIDDEN { template class aa_tree_key; class aa_node_base { public: static const bool L = false; static const bool R = true; private: typedef unsigned int level_type; aa_node_base *m_link[2]; level_type m_level; static const aa_node_base s_nil; public: aa_node_base(level_type l = 1) : m_link { const_cast(&s_nil), const_cast(&s_nil) }, m_level(l) { } bool is_nil() const { return this == &s_nil; } aa_node_base * link(bool d) { return m_link[d]; } void set_link(bool d, aa_node_base *val) { m_link[d] = val; } aa_node_base *skew(); aa_node_base *split(); void decrease_level(); static void *operator new (size_t s) { return xmalloc (s); } static void operator delete (void *p) { free (p); } }; template struct aa_node_key : public aa_node_base { typedef aa_node_base base; KEY key; explicit aa_node_key(KEY k) : key(k) { } aa_node_key * link(bool d) { return static_cast(base::link(d)); } aa_node_key *skew() { return static_cast(base::skew()); } aa_node_key *split() { return static_cast(base::split()); } }; template struct aa_node : public aa_node_key { typedef aa_node_key base; DATA data; explicit aa_node(KEY k) : base(k) { } aa_node * link(bool d) { return static_cast(base::link(d)); } }; template class aa_tree_key { public: typedef aa_node_key node; typedef node *node_ptr; protected: node_ptr m_tree; protected: aa_tree_key() : m_tree(0) { } node_ptr find(KEY k) const; static node_ptr insert_1 (node_ptr t, node_ptr n); void insert(node_ptr n); static node_ptr erase_1 (node_ptr t, KEY k, node_ptr *pfree); node_ptr erase(KEY k); }; extern template class aa_tree_key; template class aa_tree : public aa_tree_key { public: typedef aa_tree_key base; typedef aa_node node; typedef node *node_ptr; typedef void (*trav_callback)(KEY, DATA *, void *); private: static void clear_1 (node_ptr); static void traverse_1 (node_ptr, trav_callback, void *); public: aa_tree() = default; ~aa_tree() { clear(); } static void *operator new (size_t s, aa_tree* p) { return p; } DATA *find(KEY k) const { node_ptr n = static_cast(base::find (k)); return n ? &n->data : 0; } DATA *insert(KEY k) { node_ptr n = new node(k); base::insert(n); return &n->data; } void erase(KEY k) { node_ptr n = static_cast(base::erase (k)); delete n; } node_ptr remove(KEY k, DATA** data) { node_ptr n = static_cast(base::erase (k)); *data = (n ? &n->data : 0); return n; } void clear() { node_ptr n = static_cast(this->m_tree); if (n) { this->m_tree = 0; clear_1 (n); } } void traverse (trav_callback cb, void *cb_data) { node_ptr t = static_cast(this->m_tree); if (t != 0) traverse_1 (t, cb, cb_data); } }; template void aa_tree::clear_1 (node_ptr t) { if (t->is_nil()) return; clear_1 (t->link(node::L)); clear_1 (t->link(node::R)); delete t; } template void aa_tree::traverse_1 (node_ptr t, trav_callback cb, void *cb_data) { if (t->is_nil()) return; cb (t->key, &t->data, cb_data); traverse_1 (t->link(node::L), cb, cb_data); traverse_1 (t->link(node::R), cb, cb_data); } } // namespace GTM #endif // LIBITM_AATREE_H