1 // synth prototype 2 // Copyright (C) 2008 Tim Blechmann 3 // 4 // This program is free software; you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation; either version 2 of the License, or 7 // (at your option) any later version. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with this program; see the file COPYING. If not, write to 16 // the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 17 // Boston, MA 02111-1307, USA. 18 19 #pragma once 20 21 #include <cassert> 22 #include <cstdint> 23 24 #include <boost/checked_delete.hpp> 25 #include <boost/intrusive/unordered_set.hpp> 26 27 #include "utilities/aligned_class.hpp" 28 #include "utilities/named_hash_entry.hpp" 29 #include "utilities/utils.hpp" 30 31 namespace nova { 32 33 typedef std::int32_t slot_index_t; 34 typedef symbol slot_identifier_type; 35 36 namespace detail { 37 38 /** class to resolve alphanumeric string to slot id */ 39 class slot_resolver { 40 protected: 41 struct map_type : public named_hash_entry { map_typenova::detail::slot_resolver::map_type42 map_type(slot_identifier_type const& name, slot_index_t index, int number_of_values): 43 named_hash_entry(name), 44 index(index), 45 number_of_values(number_of_values) {} 46 47 const slot_index_t index; 48 const int number_of_values; 49 }; 50 51 private: 52 struct hash_value { hash_valuenova::detail::slot_resolver::hash_value53 hash_value(std::size_t v): value(v) {} 54 operator ()nova::detail::slot_resolver::hash_value55 std::size_t operator()(const char*) const { return value; } 56 57 const std::size_t value; 58 }; 59 exists(const char * str) const60 bool exists(const char* str) const { 61 return slot_resolver_map.find(str, named_hash_hash(), named_hash_equal()) != slot_resolver_map.end(); 62 } 63 64 protected: slot_resolver(void)65 slot_resolver(void): slot_resolver_map(slot_resolver_map_t::bucket_traits(buckets, resolver_map_bucket_count)) {} 66 ~slot_resolver(void)67 ~slot_resolver(void) { slot_resolver_map.clear_and_dispose(boost::checked_deleter<map_type>()); } 68 register_slot(symbol const & str,slot_index_t i,int number_of_values)69 void register_slot(symbol const& str, slot_index_t i, int number_of_values) { 70 assert(not exists(str.c_str())); 71 map_type* elem = new map_type(str, i, number_of_values); 72 bool success = slot_resolver_map.insert(*elem).second; 73 assert(success); 74 75 if (size_t(i) >= slot_names.size()) 76 slot_names.resize(i + 1, nullptr); 77 slot_names[i] = elem->name(); 78 } 79 80 public: 81 /*@{*/ 82 /** resolve slot by symbolic name 83 * 84 * \return nonnegative index of slot 85 * -1, if symbolic name cannot be resolved 86 */ resolve_slot(const char * str) const87 slot_index_t resolve_slot(const char* str) const { return resolve_slot(str, string_hash(str)); } 88 resolve_slot_with_size(const char * str,int & number_of_values) const89 slot_index_t resolve_slot_with_size(const char* str, int& number_of_values) const { 90 return resolve_slot_with_size(str, string_hash(str), number_of_values); 91 } 92 resolve_slot(const char * str,std::size_t hashed_value) const93 slot_index_t resolve_slot(const char* str, std::size_t hashed_value) const { 94 auto it = slot_resolver_map.find(str, hash_value(hashed_value), named_hash_equal()); 95 if (it == slot_resolver_map.end()) 96 return -1; 97 else 98 return it->index; 99 } 100 resolve_slot_with_size(const char * str,std::size_t hashed_value,int & number_of_values) const101 slot_index_t resolve_slot_with_size(const char* str, std::size_t hashed_value, int& number_of_values) const { 102 auto it = slot_resolver_map.find(str, hash_value(hashed_value), named_hash_equal()); 103 if (it == slot_resolver_map.end()) 104 return -1; 105 106 number_of_values = it->number_of_values; 107 return it->index; 108 } 109 /*@}*/ 110 number_of_slots() const111 size_t number_of_slots() const { return slot_names.size(); } 112 name_of_slot(size_t slot_index) const113 const char* name_of_slot(size_t slot_index) const { 114 assert(slot_index < slot_names.size()); 115 return slot_names[slot_index]; 116 } 117 118 private: 119 static const int resolver_map_bucket_count = 512; 120 121 typedef boost::intrusive::unordered_set<map_type, boost::intrusive::power_2_buckets<true>> slot_resolver_map_t; 122 slot_resolver_map_t::bucket_type buckets[resolver_map_bucket_count]; 123 slot_resolver_map_t slot_resolver_map; 124 125 std::vector<const char*> slot_names; 126 }; 127 128 } /* namespace detail */ 129 130 class abstract_synth; 131 132 struct synth_definition_deleter { operator ()nova::synth_definition_deleter133 template <typename T> void operator()(T* ptr) { dispose(static_cast<class synth_definition*>(ptr)); } 134 135 void dispose(class synth_definition*); 136 }; 137 138 /** prototype of a synth 139 * 140 * - works as a synth factory 141 * 142 * */ 143 class synth_definition : public aligned_class, 144 public named_hash_entry, 145 public intrusive_refcountable<>, 146 public detail::slot_resolver { 147 public: synth_definition(symbol const & name)148 explicit synth_definition(symbol const& name): named_hash_entry(name) {} 149 150 virtual ~synth_definition(void) = default; 151 152 virtual abstract_synth* create_instance(int node_id) = 0; 153 154 template <typename synth_t> static inline synth_t* allocate(void); 155 }; 156 157 typedef boost::intrusive_ptr<synth_definition> synth_definition_ptr; 158 159 } /* namespace nova */ 160