1 // Copyright (c) 2011-present, Facebook, Inc.  All rights reserved.
2 //  This source code is licensed under both the GPLv2 (found in the
3 //  COPYING file in the root directory) and Apache 2.0 License
4 //  (found in the LICENSE.Apache file in the root directory).
5 // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
6 // Use of this source code is governed by a BSD-style license that can be
7 // found in the LICENSE file. See the AUTHORS file for names of contributors.
8 
9 #pragma once
10 
11 #include "rocksdb/rocksdb_namespace.h"
12 
13 namespace ROCKSDB_NAMESPACE {
14 
15 class Cleanable {
16  public:
17   Cleanable();
18   // No copy constructor and copy assignment allowed.
19   Cleanable(Cleanable&) = delete;
20   Cleanable& operator=(Cleanable&) = delete;
21 
22   ~Cleanable();
23 
24   // Move constructor and move assignment is allowed.
25   Cleanable(Cleanable&&);
26   Cleanable& operator=(Cleanable&&);
27 
28   // Clients are allowed to register function/arg1/arg2 triples that
29   // will be invoked when this iterator is destroyed.
30   //
31   // Note that unlike all of the preceding methods, this method is
32   // not abstract and therefore clients should not override it.
33   typedef void (*CleanupFunction)(void* arg1, void* arg2);
34   void RegisterCleanup(CleanupFunction function, void* arg1, void* arg2);
35   void DelegateCleanupsTo(Cleanable* other);
36   // DoCleanup and also resets the pointers for reuse
Reset()37   inline void Reset() {
38     DoCleanup();
39     cleanup_.function = nullptr;
40     cleanup_.next = nullptr;
41   }
42 
43  protected:
44   struct Cleanup {
45     CleanupFunction function;
46     void* arg1;
47     void* arg2;
48     Cleanup* next;
49   };
50   Cleanup cleanup_;
51   // It also becomes the owner of c
52   void RegisterCleanup(Cleanup* c);
53 
54  private:
55   // Performs all the cleanups. It does not reset the pointers. Making it
56   // private
57   // to prevent misuse
DoCleanup()58   inline void DoCleanup() {
59     if (cleanup_.function != nullptr) {
60       (*cleanup_.function)(cleanup_.arg1, cleanup_.arg2);
61       for (Cleanup* c = cleanup_.next; c != nullptr;) {
62         (*c->function)(c->arg1, c->arg2);
63         Cleanup* next = c->next;
64         delete c;
65         c = next;
66       }
67     }
68   }
69 };
70 
71 }  // namespace ROCKSDB_NAMESPACE
72