/* Copyright (C) 2021 Free Software Foundation, Inc. Contributed by Oracle. This file is part of GNU Binutils. This program 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, or (at your option) any later version. This program 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. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _DbeSyncMap_h #define _DbeSyncMap_h #include "DbeLock.h" #include "DbeLinkList.h" #include "vec.h" typedef unsigned long hash_ty; template <class ITEM> class DbeSyncMap : public DbeLock { public: DbeSyncMap (int _chunkSize = DefaultChunkSize); virtual ~DbeSyncMap (); void reset (); ITEM *get (const char *nm, int64_t chksum); ITEM *sync_create_item (const char *nm, int64_t chksum); ITEM *get (const char *nm, const char *path, DbeFile *df); ITEM *sync_create_item (const char *nm, const char *path, DbeFile *df); virtual void dump (); Vector<ITEM *> * values () { return items; }; private: hash_ty hash (const char *key); DbeLinkList<ITEM *> **chunk; Vector<ITEM *> *items; long chunkSize; enum { DefaultChunkSize = 1024 }; }; template <class ITEM> DbeSyncMap<ITEM>::DbeSyncMap (int _chunkSize) { chunkSize = _chunkSize; chunk = new DbeLinkList<ITEM *> * [chunkSize]; for (long i = 0; i < chunkSize; i++) chunk[i] = NULL; items = new Vector<ITEM *>(512); } template <class ITEM> DbeSyncMap<ITEM>::~DbeSyncMap () { for (long i = 0; i < chunkSize; i++) Destroy (chunk[i]); delete[] chunk; delete items; } template <class ITEM> void DbeSyncMap<ITEM>::reset () { for (long i = 0; i < chunkSize; i++) { Destroy (chunk[i]); chunk[i] = NULL; } items->reset (); } template <class ITEM> ITEM * DbeSyncMap<ITEM>::get (const char *nm, int64_t chksum) { hash_ty h = hash (nm); for (DbeLinkList<ITEM *> *dl = chunk[h]; dl; dl = dl->get_next ()) { ITEM *item = dl->get_item (); if (item->compare (nm, chksum)) return item; } return NULL; } template <class ITEM> hash_ty DbeSyncMap<ITEM>::hash (const char *key) { return (hash_ty) (crc64 (key, strlen (key)) % chunkSize); } template <class ITEM> ITEM * DbeSyncMap<ITEM>::sync_create_item (const char *nm, int64_t chksum) { hash_ty h = hash (nm); for (DbeLinkList<ITEM *> *dl = chunk[h]; dl; dl = dl->get_next ()) { ITEM *item = dl->get_item (); if (item->compare (nm, chksum)) return item; } aquireLock (); for (DbeLinkList<ITEM *> *dl = chunk[h]; dl; dl = dl->get_next ()) { ITEM *item = dl->get_item (); if (item->compare (nm, chksum)) { releaseLock (); return item; } } ITEM *item = ITEM::create_item (nm, chksum); DbeLinkList<ITEM *> *dl = new DbeLinkList<ITEM *>(item); dl->set_next (chunk[h]); chunk[h] = dl; items->append (item); releaseLock (); return item; } template <class ITEM> ITEM * DbeSyncMap<ITEM>::get (const char *nm, const char *path, DbeFile *df) { int mask = 1 + (path != NULL ? 2 : 0) + (df != NULL ? 4 : 0); hash_ty h = hash (nm); for (DbeLinkList<ITEM *> *dl = chunk[h]; dl; dl = dl->get_next ()) { ITEM *item = dl->get_item (); if (mask == item->compare (nm, path, df)) return item; } return NULL; } template <class ITEM> ITEM * DbeSyncMap<ITEM>::sync_create_item (const char *nm, const char *path, DbeFile *df) { int mask = CMP_PATH; if (path != NULL) mask += CMP_RUNTIMEPATH; if (df != NULL) mask += CMP_CHKSUM; hash_ty h = hash (nm); for (DbeLinkList<ITEM *> *dl = chunk[h]; dl; dl = dl->get_next ()) { ITEM *item = dl->get_item (); if (mask == item->compare (nm, path, df)) return item; } aquireLock (); for (DbeLinkList<ITEM *> *dl = chunk[h]; dl; dl = dl->get_next ()) { ITEM *item = dl->get_item (); if (mask == item->compare (nm, path, df)) { releaseLock (); return item; } } ITEM *item = ITEM::create_item (nm, path, df); DbeLinkList<ITEM *> *dl = new DbeLinkList<ITEM *>(item); dl->set_next (chunk[h]); chunk[h] = dl; items->append (item); releaseLock (); return item; } template <class ITEM> void DbeSyncMap<ITEM>::dump () { Dprintf (1, NTXT ("\nDbeSyncMap::dump: vals=%ld\n"), (long) VecSize (items)); int tot = 0; int max_cnt = 0; for (long i = 0; i < chunkSize; i++) { DbeLinkList<ITEM *> *lp = chunk[i]; if (lp) { int cnt = 0; for (DbeLinkList<ITEM *> *lp1 = lp; lp1; lp1 = lp1->get_next ()) cnt++; tot += cnt; if (max_cnt < cnt) max_cnt = cnt; cnt = 1; for (DbeLinkList<ITEM *> *lp1 = lp; lp1; lp1 = lp1->get_next ()) { ITEM *p = lp1->get_item (); Dprintf (1, NTXT (" %2d %s\n"), cnt, p->get_name ()); cnt++; } } } Dprintf (1, NTXT ("\nDbeSyncMap::dump: vals=%ld max_cnt=%d tot=%d\n"), (long) VecSize (items), max_cnt, tot); } #endif /* _DbeSyncMap_h */