3

I am looking through the source code for MongoDB, and see the following declaration inside of a function, which I don't understand and haven't seen in my C programming experience.

Lock::DBLock dbLock(txn->lockState(), ns.db(), MODE_X);

I am trying to understand what this declaration is doing in C++ terms (ie. I want to understand the syntax, not specifics about the functionality of what is going on).

This breaks down into two main questions: 1) What is the purpose of the Lock::DBLock statement in front of the function? 2) Is this a function call, or a function declaration?

royhowie
  • 11,075
  • 14
  • 50
  • 67
Alexander Marquardt
  • 1,539
  • 15
  • 30
  • 2
    That's not a function, that's a variable named `dbLock`, which has type `Lock::DBLock`, and is created using a constructor which is passed three values. – Dietrich Epp Jan 27 '16 at 22:52
  • 1
    It's analogous to `int some_integer_variable(3);` which declares a variable and initializes it. – Barmar Jan 27 '16 at 22:54

2 Answers2

17

It is a variable declaration with a constructor - so it's BOTH a function call [to the object constructor] and a declaration of a variable.

It declares a variable of the type;

  Lock::DBLock

The variable is called dbLock. It calls the constructor with a txn->lockState(), the ns.db() and a MODE_X.

My guess is that txn->lockState actually returns a lock-object, and the thing we're locking is ns.db() - in "exclusive mode". But that's a guess, and you have to look those things up within the environment.

Without looking up the documentation, I expect Lock::DBLock is a "lock manager", in other words, it takes the lock when created, and releases when destroyed.

A simple lock manager would look something like this:

 class LockMgr
 {
      LockMgr(SomeLockType &X) : keeper(X)
      {
         keeper.Lock();
      }
      ~LockMgr()
      {
         keeper.Unlock();
      }
      private:
        SomeLockType& keeper;    // Must be reference to original lock
 };

The destructor is automatically called when the variable goes out of scope (in other worse when you leave the {} pair that the variable is within.

In C++, one commmon strategy for "resource handling" is called RAII (Resource Acquisition Is Initialization) - a variable is used to hold a resource, and it is assigned during initialization. This helps a lot with "not forgetting to undo" - for example in code that returns in the middle of the function, does break to exit a loop, or similar things. In C, you always have to watch your step for releasing locks, closing files, freeing memory, etc - and of course, if you use C++ in the wrong way, you can fall into the same pitfalls there - calling new will definitely need a call to delete, directly calling a locks Lock() member function requires a Unlock() call somewhere. But if we "wrap" the resource into an object that holds it for the duration we need it, and automatically "lets go" (frees, unlocks, etc) in the destructor, there's no need to remember to release memory, unlock locks, etc, etc.

I would suggest that before asking further questions, you read the first chapter about classes and constructor & destructor pairs in your C++ book (you DO have a book, right?)

Community
  • 1
  • 1
Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
8

The code is the declaration of a variable named dbLock of type Lock::DBLock. The parenthesized list contains arguments to a constructor for that type.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157