~ubuntu-branches/ubuntu/wily/mozjs17/wily

« back to all changes in this revision

Viewing changes to mfbt/GuardObjects.h

  • Committer: Package Import Robot
  • Author(s): Rico Tzschichholz
  • Date: 2013-05-25 12:24:23 UTC
  • Revision ID: package-import@ubuntu.com-20130525122423-zmxucrhtensw90xy
Tags: upstream-17.0.0
ImportĀ upstreamĀ versionĀ 17.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 
2
/* This Source Code Form is subject to the terms of the Mozilla Public
 
3
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 
4
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
5
 
 
6
/* Implementation of macros to ensure correct use of RAII Auto* objects. */
 
7
 
 
8
#ifndef mozilla_GuardObjects_h
 
9
#define mozilla_GuardObjects_h
 
10
 
 
11
#include "mozilla/Assertions.h"
 
12
#include "mozilla/Types.h"
 
13
 
 
14
#ifdef __cplusplus
 
15
 
 
16
#ifdef DEBUG
 
17
 
 
18
namespace mozilla {
 
19
namespace detail {
 
20
 
 
21
/*
 
22
 * The following classes are designed to cause assertions to detect
 
23
 * inadvertent use of guard objects as temporaries. In other words,
 
24
 * when we have a guard object whose only purpose is its constructor and
 
25
 * destructor (and is never otherwise referenced), the intended use
 
26
 * might be:
 
27
 *
 
28
 *   AutoRestore savePainting(mIsPainting);
 
29
 *
 
30
 * but is is easy to accidentally write:
 
31
 *
 
32
 *   AutoRestore(mIsPainting);
 
33
 *
 
34
 * which compiles just fine, but runs the destructor well before the
 
35
 * intended time.
 
36
 *
 
37
 * They work by adding (#ifdef DEBUG) an additional parameter to the
 
38
 * guard object's constructor, with a default value, so that users of
 
39
 * the guard object's API do not need to do anything. The default value
 
40
 * of this parameter is a temporary object. C++ (ISO/IEC 14882:1998),
 
41
 * section 12.2 [class.temporary], clauses 4 and 5 seem to assume a
 
42
 * guarantee that temporaries are destroyed in the reverse of their
 
43
 * construction order, but I actually can't find a statement that that
 
44
 * is true in the general case (beyond the two specific cases mentioned
 
45
 * there). However, it seems to be true.
 
46
 *
 
47
 * These classes are intended to be used only via the macros immediately
 
48
 * below them:
 
49
 *
 
50
 *   MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER declares (ifdef DEBUG) a member
 
51
 *     variable, and should be put where a declaration of a private
 
52
 *     member variable would be placed.
 
53
 *   MOZ_GUARD_OBJECT_NOTIFIER_PARAM should be placed at the end of the
 
54
 *     parameters to each constructor of the guard object; it declares
 
55
 *     (ifdef DEBUG) an additional parameter. (But use the *_ONLY_PARAM
 
56
 *     variant for constructors that take no other parameters.)
 
57
 *   MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL should likewise be used in
 
58
 *     the implementation of such constructors when they are not inline.
 
59
 *   MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT should be used in
 
60
 *     the implementation of such constructors to pass the parameter to
 
61
 *     a base class that also uses these macros
 
62
 *   MOZ_GUARD_OBJECT_NOTIFIER_INIT is a statement that belongs in each
 
63
 *     constructor. It uses the parameter declared by
 
64
 *     MOZ_GUARD_OBJECT_NOTIFIER_PARAM.
 
65
 *
 
66
 * For more details, and examples of using these macros, see
 
67
 * https://developer.mozilla.org/en/Using_RAII_classes_in_Mozilla
 
68
 */
 
69
class MOZ_EXPORT_API(GuardObjectNotifier)
 
70
{
 
71
  private:
 
72
    bool* statementDone;
 
73
 
 
74
  public:
 
75
    GuardObjectNotifier() : statementDone(NULL) { }
 
76
 
 
77
    ~GuardObjectNotifier() {
 
78
      *statementDone = true;
 
79
    }
 
80
 
 
81
    void setStatementDone(bool* statementIsDone) {
 
82
      statementDone = statementIsDone;
 
83
    }
 
84
};
 
85
 
 
86
class MOZ_EXPORT_API(GuardObjectNotificationReceiver)
 
87
{
 
88
  private:
 
89
    bool statementDone;
 
90
 
 
91
  public:
 
92
    GuardObjectNotificationReceiver() : statementDone(false) { }
 
93
 
 
94
    ~GuardObjectNotificationReceiver() {
 
95
      /*
 
96
       * Assert that the guard object was not used as a temporary.  (Note that
 
97
       * this assert might also fire if init is not called because the guard
 
98
       * object's implementation is not using the above macros correctly.)
 
99
       */
 
100
      MOZ_ASSERT(statementDone);
 
101
    }
 
102
 
 
103
    void init(const GuardObjectNotifier& constNotifier) {
 
104
      /*
 
105
       * constNotifier is passed as a const reference so that we can pass a
 
106
       * temporary, but we really intend it as non-const.
 
107
       */
 
108
      GuardObjectNotifier& notifier = const_cast<GuardObjectNotifier&>(constNotifier);
 
109
      notifier.setStatementDone(&statementDone);
 
110
    }
 
111
};
 
112
 
 
113
} /* namespace detail */
 
114
} /* namespace mozilla */
 
115
 
 
116
#endif /* DEBUG */
 
117
 
 
118
#ifdef DEBUG
 
119
#  define MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER \
 
120
     mozilla::detail::GuardObjectNotificationReceiver _mCheckNotUsedAsTemporary;
 
121
#  define MOZ_GUARD_OBJECT_NOTIFIER_PARAM \
 
122
     , const mozilla::detail::GuardObjectNotifier& _notifier = \
 
123
         mozilla::detail::GuardObjectNotifier()
 
124
#  define MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM \
 
125
     const mozilla::detail::GuardObjectNotifier& _notifier = \
 
126
         mozilla::detail::GuardObjectNotifier()
 
127
#  define MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL \
 
128
     , const mozilla::detail::GuardObjectNotifier& _notifier
 
129
#  define MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT \
 
130
     , _notifier
 
131
#  define MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_TO_PARENT \
 
132
       _notifier
 
133
#  define MOZ_GUARD_OBJECT_NOTIFIER_INIT \
 
134
     do { _mCheckNotUsedAsTemporary.init(_notifier); } while (0)
 
135
#else
 
136
#  define MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 
137
#  define MOZ_GUARD_OBJECT_NOTIFIER_PARAM
 
138
#  define MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM
 
139
#  define MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL
 
140
#  define MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_TO_PARENT
 
141
#  define MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT
 
142
#  define MOZ_GUARD_OBJECT_NOTIFIER_INIT do { } while (0)
 
143
#endif
 
144
 
 
145
#endif /* __cplusplus */
 
146
 
 
147
#endif /* mozilla_GuardObjects_h */