BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bslalg_hashtableanchor.h
Go to the documentation of this file.
1/// @file bslalg_hashtableanchor.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bslalg_hashtableanchor.h -*-C++-*-
8#ifndef INCLUDED_BSLALG_HASHTABLEANCHOR
9#define INCLUDED_BSLALG_HASHTABLEANCHOR
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bslalg_hashtableanchor bslalg_hashtableanchor
15/// @brief Provide a type holding the constituent parts of a hash table.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bslalg
19/// @{
20/// @addtogroup bslalg_hashtableanchor
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bslalg_hashtableanchor-purpose"> Purpose</a>
25/// * <a href="#bslalg_hashtableanchor-classes"> Classes </a>
26/// * <a href="#bslalg_hashtableanchor-description"> Description </a>
27/// * <a href="#bslalg_hashtableanchor-attributes"> Attributes </a>
28/// * <a href="#bslalg_hashtableanchor-usage"> Usage </a>
29/// * <a href="#bslalg_hashtableanchor-example-1-basic-usage"> Example 1: Basic Usage </a>
30///
31/// # Purpose {#bslalg_hashtableanchor-purpose}
32/// Provide a type holding the constituent parts of a hash table.
33///
34/// # Classes {#bslalg_hashtableanchor-classes}
35///
36/// - bslalg::HashTableAnchor: (in-core) bucket-array and node list
37///
38/// @see bslstl_hashtable, bslalg_hashtableimputil
39///
40/// # Description {#bslalg_hashtableanchor-description}
41/// This component provides a single, complex-constrained
42/// **in-core** (value-semantic) attribute class, `bslalg::HashTableAnchor`,
43/// that is used to hold (not own) the array of buckets and the list of nodes
44/// that form the key data elements of a hash-table. This class is typically
45/// used with the utilities provided in @ref bslstl_hashtableimputil . Note that
46/// the decision to store nodes in a linked list (i.e., resolving collisions
47/// through chaining) is intended to facilitate a hash-table implementation
48/// meeting the requirements of a C++11 standard unordered container.
49///
50/// ## Attributes {#bslalg_hashtableanchor-attributes}
51///
52///
53/// @code
54/// Name Type Simple Constraints
55/// ------------------ ------------------- ------------------
56/// bucketArrayAddress HashTableBucket * none
57///
58/// bucketArraySize size_t none
59///
60/// listRootAddress BidirectionalLink * none
61///
62///
63/// Complex Constraint
64/// -------------------------------------------------------------------------
65/// `bucketArrayAddress` must refer to a contiguous sequence of valid
66/// `bslalg::HashTableBucket` objects of at least the specified
67/// `bucketArraySize` or both `bucketArrayAddress` and `bucketArraySize` must
68/// be 0.
69/// @endcode
70///
71/// * `listRootAddress`: address of the head of the linked list of nodes
72/// holding the elements contained in a hash table
73/// * `bucketArrayAddress`: address of the first element of the sequence of
74/// `HashTableBucket` objects, each of which refers to the first and last
75/// node (from `listRootAddress`) in that bucket
76/// * `bucketArraySize`: the number of (contiguous) buckets in the array of
77/// buckets at `bucketArrayAddress`
78///
79/// ## Usage {#bslalg_hashtableanchor-usage}
80///
81///
82/// This section illustrates intended use of this component.
83///
84/// ### Example 1: Basic Usage {#bslalg_hashtableanchor-example-1-basic-usage}
85///
86///
87/// Suppose we want to create a hash table that keeps track of pointers.
88/// Pointers can be added (`insert`ed) or removed (`erase`d) from the table, and
89/// the table will keep track, at any time, of whether a pointer is currently
90/// stored in the table using the `count` method. It will also be able to
91/// return the total number of objects stored in the table (the `size` method).
92/// Redundant `insert`s have no effect -- a given pointer may only be stored in
93/// the table once.
94///
95/// First, we create our class:
96/// @code
97/// class PtrHashSet : public bslalg::HashTableAnchor {
98/// // PRIVATE TYPES
99/// typedef bsls::Types::UintPtr UintPtr;
100/// typedef bslalg::BidirectionalNode<void *> Node;
101/// typedef bslalg::HashTableBucket Bucket;
102/// typedef bslalg::BidirectionalLinkListUtil Util;
103///
104/// // DATA
105/// double d_maxLoadFactor;
106/// unsigned d_numNodes;
107/// bslma::Allocator *d_allocator_p;
108///
109/// // PRIVATE MANIPULATORS
110///
111/// /// Roughly double the number of buckets, such that the number of
112/// /// buckets shall always be `2^N - 1`.
113/// void grow();
114///
115/// // PRIVATE ACCESSORS
116///
117/// /// Perform sanity checks on this table, returning `true` if all the
118/// /// tests pass and `false` otherwise. Note that many of the checks
119/// /// are done with the `ASSERTV` macro and will cause messages to be
120/// /// written to the console.
121/// bool checkInvariants() const;
122///
123/// /// If the specified value `ptr` is stored in this table, return
124/// /// pointers to its node and bucket in the specified 'node' and
125/// /// `bucket`. If it is not in this table, return the bucket it
126/// /// should be in, and a pointer to the first node, if any, in that
127/// /// bucket. If the bucket is empty, return with
128/// /// `*node == listRootAddress()`. Return `true` if `ptr` was found
129/// /// in the table and `false` otherwise. Note that it is permissible
130/// /// to pass 0 to `node` and / or `bucket`, in which case these
131/// /// arguments are ignored.
132/// bool find(Node **node, Bucket **bucket, const void *ptr) const;␇
133///
134/// private:
135/// // NOT IMPLEMENTED
136/// PtrHashSet(const PtrHashSet&, bslma::Allocator *);
137/// PtrHashSet& operator=(const PtrHashSet&);
138///
139/// public:
140/// // CREATORS
141///
142/// /// Create a `PtrHashSet`, using the specified `allocator`. If no
143/// /// allocator is specified, use the default allocator.
144/// explicit
145/// PtrHashSet(bslma::Allocator *allocator = 0);
146///
147/// /// Destroy this `PtrHashSet`, freeing all its memory.
148/// ~PtrHashSet();
149///
150/// // MANIPULATORS
151///
152/// /// If the specfied `ptr` is not in this hash table, add it,
153/// /// returning `true`. If it is already in the table, return `false`
154/// /// with no action taken.
155/// bool insert(void *ptr);
156///
157/// /// If the specfied `ptr` is in this hash table, remove it,
158/// /// returning `true`. If it is not found in the table, return
159/// /// `false` with no action taken.
160/// bool erase(void *ptr);
161///
162/// // ACCESSORS
163///
164/// /// Return 1 if the specified value `ptr` is in this table and 0
165/// /// otherwise.
166/// std::size_t count(void *ptr) const;
167///
168/// /// Return the number of discrete values that are stored in this
169/// /// table.
170/// std::size_t size() const;
171/// };
172///
173/// // PRIVATE MANIPULATORS
174/// void PtrHashSet::grow()
175/// {
176/// // 'bucketArraySize' will always be '2^N - 1', so that when pointers
177/// // are aligned by some 2^N they're likely to be relatively prime.
178///
179/// std::size_t newBucketArraySize = bucketArraySize() * 2 + 1;
180/// std::size_t newBucketArraySizeInBytes =
181/// newBucketArraySize * sizeof(Bucket);
182/// memset(bucketArrayAddress(), 0x5a, size() * sizeof(Bucket));
183/// d_allocator_p->deallocate(bucketArrayAddress());
184/// setBucketArrayAddressAndSize(
185/// (Bucket *) d_allocator_p->allocate(newBucketArraySizeInBytes),
186/// newBucketArraySize);
187/// memset(bucketArrayAddress(), 0, newBucketArraySizeInBytes);
188/// Node *newListRootAddress = 0;
189///
190/// unsigned numNodes = 0;
191/// for (Node *node = (Node *) listRootAddress(); node; ++numNodes) {
192/// Node *rippedOut = node;
193/// node = (Node *) node->nextLink();
194///
195/// std::size_t index =
196/// (UintPtr) rippedOut->value() % bucketArraySize();
197/// Bucket& bucket = bucketArrayAddress()[index];
198/// if (bucket.first()) {
199/// if (0 == bucket.first()->previousLink()) {
200/// newListRootAddress = rippedOut;
201/// }
202/// Util::insertLinkBeforeTarget(rippedOut, bucket.first());
203/// bucket.setFirst(rippedOut);
204/// }
205/// else {
206/// Util::insertLinkBeforeTarget(rippedOut,
207/// newListRootAddress);
208/// newListRootAddress = rippedOut;
209/// bucket.setFirstAndLast(rippedOut, rippedOut);
210/// }
211/// }
212/// assert(size() == numNodes);
213///
214/// setListRootAddress(newListRootAddress);
215///
216/// checkInvariants();
217/// }
218///
219/// // PRIVATE ACCESSORS
220/// bool PtrHashSet::checkInvariants() const
221/// {
222/// bool ok;
223///
224/// unsigned numNodes = 0;
225/// Node *prev = 0;
226/// for (Node *node = (Node *) listRootAddress(); node;
227/// prev = node, node = (Node *) node->nextLink()) {
228/// ok = node->previousLink() == prev;
229/// assert(ok && "node->previousLink() == prev");
230/// if (!ok) return false; // RETURN
231/// ++numNodes;
232/// }
233/// ok = size() == numNodes;
234/// assert(ok && "size() == numNodes");
235/// if (!ok) return false; // RETURN
236///
237/// numNodes = 0;
238/// for (unsigned i = 0; i < bucketArraySize(); ++i) {
239/// Bucket& bucket = bucketArrayAddress()[i];
240/// if (bucket.first()) {
241/// ++numNodes;
242/// for (Node *node = (Node *) bucket.first();
243/// bucket.last() != node;
244/// node = (Node *) node->nextLink()) {
245/// ++numNodes;
246/// }
247/// }
248/// else {
249/// ok = !bucket.last();
250/// assert(ok && "!bucket.last()");
251/// if (!ok) return false; // RETURN
252/// }
253/// }
254/// ok = size() == numNodes;
255/// assert(ok && "size() == numNodes");
256///
257/// return ok;
258/// }
259///
260/// bool PtrHashSet::find(Node **node, Bucket **bucket, const void *ptr) const
261/// {
262/// Node *dummyNodePtr;
263/// Bucket *dummyBucketPtr;
264/// if (!node ) node = &dummyNodePtr;
265/// if (!bucket) bucket = &dummyBucketPtr;
266///
267/// Node *& nodePtrRef = *node;
268/// unsigned index = (UintPtr) ptr % bucketArraySize();
269/// Bucket& bucketRef = bucketArrayAddress()[index];
270/// *bucket = &bucketRef;
271/// if (bucketRef.first()) {
272/// Node *begin = (Node *) bucketRef.first();
273/// Node * const end = (Node *) bucketRef.last()->nextLink();
274/// for (Node *n = begin; end != n; n = (Node *) n->nextLink()) {
275/// if (n->value() == ptr) {
276/// // found
277///
278/// nodePtrRef = n;
279/// return true; // RETURN
280/// }
281/// }
282/// // not found
283///
284/// nodePtrRef = begin;
285/// return false; // RETURN
286/// }
287/// // empty bucket
288///
289/// nodePtrRef = (Node *) listRootAddress();
290/// return false;
291/// }
292///
293/// // CREATORS
294/// PtrHashSet::PtrHashSet(bslma::Allocator *allocator)
295/// : HashTableAnchor(0, 0, 0)
296/// , d_maxLoadFactor(0.4)
297/// , d_numNodes(0)
298/// {
299/// enum { NUM_BUCKETS = 3 };
300///
301/// d_allocator_p = bslma::Default::allocator(allocator);
302/// std::size_t bucketArraySizeInBytes = NUM_BUCKETS * sizeof(Bucket);
303///
304/// setBucketArrayAddressAndSize(
305/// (Bucket *) d_allocator_p->allocate(bucketArraySizeInBytes),
306/// NUM_BUCKETS);
307/// memset(bucketArrayAddress(), 0, bucketArraySizeInBytes);
308/// }
309///
310/// PtrHashSet::~PtrHashSet()
311/// {
312/// BSLS_ASSERT_SAFE(checkInvariants());
313///
314/// for (Node *node = (Node *) listRootAddress(); node; ) {
315/// Node *toDelete = node;
316/// node = (Node *) node->nextLink();
317///
318/// memset(toDelete, 0x5a, sizeof(*toDelete));
319/// d_allocator_p->deallocate(toDelete);
320/// }
321///
322/// d_allocator_p->deallocate(bucketArrayAddress());
323/// }
324///
325/// // MANIPULATORS
326/// bool PtrHashSet::erase(void *ptr)
327/// {
328/// Bucket *bucket;
329/// Node *node;
330///
331/// if (!find(&node, &bucket, ptr)) {
332/// return false; // RETURN
333/// }
334///
335/// if (bucket->first() == node) {
336/// if (bucket->last() == node) {
337/// bucket->reset();
338/// }
339/// else {
340/// bucket->setFirst(node->nextLink());
341/// }
342/// }
343/// else if (bucket->last() == node) {
344/// bucket->setLast(node->previousLink());
345/// }
346///
347/// --d_numNodes;
348/// Util::unlink(node);
349///
350/// d_allocator_p->deallocate(node);
351///
352/// checkInvariants();
353///
354/// return true;
355/// }
356///
357/// bool PtrHashSet::insert(void *ptr)
358/// {
359/// Bucket *bucket;
360/// Node *insertionPoint;
361///
362/// if (find(&insertionPoint, &bucket, ptr)) {
363/// // Already in set, do nothing.
364///
365/// return false; // RETURN
366/// }
367///
368/// if (bucketArraySize() * d_maxLoadFactor < d_numNodes + 1) {
369/// grow();
370/// bool found = find(&insertionPoint, &bucket, ptr);
371/// BSLS_ASSERT_SAFE(!found);
372/// }
373///
374/// ++d_numNodes;
375/// Node *node = (Node *) d_allocator_p->allocate(sizeof(Node));
376///
377/// Util::insertLinkBeforeTarget(node, insertionPoint);
378/// node->value() = ptr;
379/// if (listRootAddress() == insertionPoint) {
380/// BSLS_ASSERT_SAFE(0 == node->previousLink());
381/// setListRootAddress(node);
382/// }
383///
384/// if (bucket->first()) {
385/// BSLS_ASSERT_SAFE(bucket->first() == insertionPoint);
386///
387/// bucket->setFirst(node);
388/// }
389/// else {
390/// BSLS_ASSERT_SAFE(!bucket->last());
391///
392/// bucket->setFirstAndLast(node, node);
393/// }
394///
395/// assert(count(ptr));
396///
397/// checkInvariants();
398///
399/// return true;
400/// }
401///
402/// // ACCESSORS
403/// std::size_t PtrHashSet::count(void *ptr) const
404/// {
405/// return find(0, 0, ptr);
406/// }
407///
408/// std::size_t PtrHashSet::size() const
409/// {
410/// return d_numNodes;
411/// }
412/// @endcode
413/// Then, in `main`, we create a test allocator for use in this example to
414/// ensure that no memory is leaked:
415/// @code
416/// bslma::TestAllocator ta("test", veryVeryVeryVerbose);
417/// @endcode
418/// Next, we declare our table using that allocator:
419/// @code
420/// PtrHashSet phs(&ta);
421/// @endcode
422/// Then, we create an area of memory from which our pointers will come:
423/// @code
424/// enum { SEGMENT_LENGTH = 1000 };
425/// char *pc = (char *) ta.allocate(SEGMENT_LENGTH);
426/// @endcode
427/// Next, we iterate through the length of the segment, insert those pointers
428/// for which `ptr - pc == N * 7` is true. We keep a count of the number of
429/// items we insert into the table in the variable `sevens`:
430/// @code
431/// unsigned sevens = 0;
432/// for (int i = 0; i < SEGMENT_LENGTH; i += 7) {
433/// ++sevens;
434/// bool status = phs.insert(&pc[i]);
435/// assert(status);
436/// }
437/// @endcode
438/// Then, we verify the number of objects we've placed in the table:
439/// @code
440/// assert(phs.size() == sevens);
441/// @endcode
442/// Next, we iterate through ALL pointers in the `pc` array, using the `count`
443/// method to verify that the ones we expect are in the table:
444/// @code
445/// for (int i = 0; i < SEGMENT_LENGTH; ++i) {
446/// assert(phs.count(&pc[i]) == (0 == i % 7));
447/// }
448/// @endcode
449/// Then, we iterate, deleting all elements from the table for which
450/// `ptr - pc == 3 * N` is true. We keep a count of the number of elements that
451/// were deleted from the table in the variable `killed`:
452/// @code
453/// unsigned killed = 0;
454/// for (int i = 0; i < SEGMENT_LENGTH; i += 3) {
455/// const bool deleted = phs.erase(&pc[i]);
456/// assert(deleted == (0 == i % 7));
457/// killed += deleted;
458/// }
459/// @endcode
460/// Next, we verify the number of remaining elements in the table:
461/// @code
462/// assert(killed < sevens);
463/// assert(phs.size() == sevens - killed);
464/// @endcode
465/// Then, in verbose mode we print our tallies:
466/// @code
467/// if (verbose) {
468/// printf("sevens = %u, killed = %u, phs.size() = %u\n", sevens,
469/// killed, (unsigned) phs.size());
470/// }
471/// @endcode
472/// Now, we iterate through every element of the `pc` array, verifying that the
473/// surviving elements are exactly those for which `ptr - pc` was divisible by 7
474/// and not by 3:
475/// @code
476/// for (int i = 0; i < SEGMENT_LENGTH; ++i) {
477/// const bool present = phs.count(&pc[i]);
478/// assert(present == ((0 == i % 7) && (0 != i % 3)));
479/// }
480/// @endcode
481/// Finally, we clean up our `pc` array:
482/// @code
483/// ta.deallocate(pc);
484/// @endcode
485/// @}
486/** @} */
487/** @} */
488
489/** @addtogroup bsl
490 * @{
491 */
492/** @addtogroup bslalg
493 * @{
494 */
495/** @addtogroup bslalg_hashtableanchor
496 * @{
497 */
498
499#include <bslscm_version.h>
500
503
506
507#include <bsls_assert.h>
508
509#include <cstddef>
510
511#ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
512#include <bsls_nativestd.h>
513#endif // BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
514
515
516
517namespace bslalg {
518
519struct HashTableBucket; // This is known to be a POD struct.
520
521 // =============================
522 // class bslalg::HashTableAnchor
523 // =============================
524
525/// This complex constrained *in*-*core* (value-semantic) attribute class
526/// characterizes the key data elements of a hash table. See the
527/// @ref bslalg_hashtableanchor-attributes section information on the class attributes. Note that the
528/// class invariant is the identically the complex constraint of this
529/// component.
530///
531/// This class:
532/// * supports a complete set of *value-semantic* operations
533/// - except for `bdex` serialization and default construction
534/// * is **in-core**
535/// * is **exception-neutral** (agnostic)
536/// * is **alias-safe**
537/// * is `const` **thread-safe**
538/// For terminology see @ref bsldoc_glossary .
539///
540/// See @ref bslalg_hashtableanchor
542
543 // DATA
544 HashTableBucket *d_bucketArrayAddress_p; // address of the array of
545 // buckets (held, not owned)
546
547 std::size_t d_bucketArraySize; // size of 'd_bucketArray'
548
549 BidirectionalLink *d_listRootAddress_p; // head of the list of
550 // elements in the hash-table
551 // (held, not owned)
552
553 public:
554 // TRAITS
557
558 // CREATORS
559
560 /// Create a `bslalg::HashTableAnchor` object having the specified
561 /// `bucketArrayAddress`, `bucketArraySize`, and `listRootAddress`
562 /// attributes. The behavior is undefined unless `bucketArrayAddress`
563 /// refers to a contiguous sequence of valid `bslalg::HashTableBucket`
564 /// objects of at least `bucketArraySize` or unless both
565 /// `bucketArrayAddress` and `bucketArraySize` are 0.
567 std::size_t bucketArraySize,
569
570 /// Create a `bslalg::HashTableAnchor` object having the same value
571 /// as the specified `original` object.
572 HashTableAnchor(const HashTableAnchor& original);
573
574 /// Destroy this object.
576
577 // MANIPULATORS
578
579 /// Assign to this object the value of the specified `rhs` object, and
580 /// return a reference providing modifiable access to this object.
582
583 /// Set the bucket array address and bucket array size attributes of
584 /// this object to the specified `bucketArrayAddress` and
585 /// `bucketArraySize` values. The behavior is undefined unless
586 /// `bucketArrayAddress` refers to a contiguous sequence of valid
587 /// `bslalg::HashTableBucket` objects of at least `bucketArraySize`, or
588 /// unless both `bucketArrayAddress` and `bucketArraySize` are 0.
590 std::size_t bucketArraySize);
591
592 /// Set the `listRootAddress` attribute of this object to the
593 /// specified `value`.
595
596 // Aspects
597
598 /// Efficiently exchange the value of this object with the value of the
599 /// specified `other` object. This method provides the no-throw
600 /// exception-safety guarantee.
601 void swap(HashTableAnchor& other);
602
603 // ACCESSORS
604
605 /// Return the value of the `bucketArrayAddress` attribute of this
606 /// object.
608
609 /// Return the value of the `bucketArraySize` attribute of this object.
610 std::size_t bucketArraySize() const;
611
612 /// Return the value `listRootAddress` attribute of this object.
614};
615
616// FREE OPERATORS
617
618/// Return `true` if the specified `lhs` and `rhs` objects have the same value,
619/// and `false` otherwise. Two `bslalg::HashTableAnchor` objects have the same
620/// value if all of the corresponding values of their `bucketArrayAddress`,
621/// `bucketArraySize`, and `listRootAddress` attributes are the same.
622bool operator==(const HashTableAnchor& lhs, const HashTableAnchor& rhs);
623
624/// Return `true` if the specified `lhs` and `rhs` objects do not have the same
625/// value, and `false` otherwise. Two `bslalg::HashTableAnchor` objects do not
626/// have the same value if any of the corresponding values of their
627/// `bucketArrayAddress`, `bucketArraySize`, or `listRootAddress` attributes
628/// are not the same.
629bool operator!=(const HashTableAnchor& lhs, const HashTableAnchor& rhs);
630
631// FREE FUNCTIONS
632
633/// Efficiently exchange the values of the specified `a` and `b` objects. This
634/// function provides the no-throw exception-safety guarantee. The behavior is
635/// undefined unless the two objects were created with the same allocator.
637
638// ============================================================================
639// INLINE FUNCTION DEFINITIONS
640// ============================================================================
641
642 // -----------------------------
643 // class bslalg::HashTableAnchor
644 // -----------------------------
645
646// CREATORS
647inline
649 std::size_t bucketArraySize,
650 bslalg::BidirectionalLink *listRootAddress)
651: d_bucketArrayAddress_p(bucketArrayAddress)
652, d_bucketArraySize(bucketArraySize)
653, d_listRootAddress_p(listRootAddress)
654{
658}
659
660inline
662: d_bucketArrayAddress_p(original.d_bucketArrayAddress_p)
663, d_bucketArraySize(original.d_bucketArraySize)
664, d_listRootAddress_p(original.d_listRootAddress_p)
665{
666}
667
668// MANIPULATORS
669inline
670HashTableAnchor& HashTableAnchor::operator=(const HashTableAnchor& rhs)
671{
672 d_bucketArrayAddress_p = rhs.d_bucketArrayAddress_p;
673 d_bucketArraySize = rhs.d_bucketArraySize;
674 d_listRootAddress_p = rhs.d_listRootAddress_p;
675 return *this;
676}
677
678inline
680 HashTableBucket *bucketArrayAddress,
681 std::size_t bucketArraySize)
682{
685
686 d_bucketArrayAddress_p = bucketArrayAddress;
687 d_bucketArraySize = bucketArraySize;
688}
689
690inline
692{
693 BSLS_ASSERT_SAFE(!value || !value->previousLink());
694
695 d_listRootAddress_p = value;
696}
697
698 // Aspects
699
700inline
705
706// ACCESSORS
707inline
709{
710 return d_listRootAddress_p;
711}
712
713inline
715{
716 return d_bucketArraySize;
717}
718
719inline
721{
722 return d_bucketArrayAddress_p;
723}
724
725} // close package namespace
726
727// FREE OPERATORS
728inline
730{
731 a.swap(b);
732}
733
734inline
736 const bslalg::HashTableAnchor& rhs)
737{
738 return lhs.bucketArrayAddress() == rhs.bucketArrayAddress()
739 && lhs.bucketArraySize() == rhs.bucketArraySize()
740 && lhs.listRootAddress() == rhs.listRootAddress();
741}
742
743inline
745 const bslalg::HashTableAnchor& rhs)
746{
747 return lhs.bucketArrayAddress() != rhs.bucketArrayAddress()
748 || lhs.bucketArraySize() != rhs.bucketArraySize()
749 || lhs.listRootAddress() != rhs.listRootAddress();
750}
751
752
753
754#endif
755
756// ----------------------------------------------------------------------------
757// Copyright 2013 Bloomberg Finance L.P.
758//
759// Licensed under the Apache License, Version 2.0 (the "License");
760// you may not use this file except in compliance with the License.
761// You may obtain a copy of the License at
762//
763// http://www.apache.org/licenses/LICENSE-2.0
764//
765// Unless required by applicable law or agreed to in writing, software
766// distributed under the License is distributed on an "AS IS" BASIS,
767// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
768// See the License for the specific language governing permissions and
769// limitations under the License.
770// ----------------------------- END-OF-FILE ----------------------------------
771
772/** @} */
773/** @} */
774/** @} */
Definition bslalg_hashtableanchor.h:541
BidirectionalLink * listRootAddress() const
Return the value listRootAddress attribute of this object.
Definition bslalg_hashtableanchor.h:708
void setBucketArrayAddressAndSize(HashTableBucket *bucketArrayAddress, std::size_t bucketArraySize)
Definition bslalg_hashtableanchor.h:679
~bslalg HashTableAnchor()
Destroy this object.
std::size_t bucketArraySize() const
Return the value of the bucketArraySize attribute of this object.
Definition bslalg_hashtableanchor.h:714
void swap(HashTableAnchor &other)
Definition bslalg_hashtableanchor.h:701
BSLMF_NESTED_TRAIT_DECLARATION(HashTableAnchor, bslmf::IsBitwiseCopyable)
void setListRootAddress(BidirectionalLink *value)
Definition bslalg_hashtableanchor.h:691
HashTableBucket * bucketArrayAddress() const
Definition bslalg_hashtableanchor.h:720
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1762
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bdlc_flathashmap.h:1805
void swap(HashTableAnchor &a, HashTableAnchor &b)
bool operator==(const HashTableAnchor &lhs, const HashTableAnchor &rhs)
bool operator!=(const HashTableAnchor &lhs, const HashTableAnchor &rhs)
Definition bslalg_hashtablebucket.h:297
static void swap(LHS_TYPE &lhs, RHS_TYPE &rhs)
Definition bslalg_scalarprimitives.h:2483
Definition bslmf_isbitwisecopyable.h:298