<commit_before>/*
 * Copyright (C) 2009, <NAME>.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */
#ifndef LIBPORT_DESTRUCTIBLE_HXX
# define LIBORT_DESTRUCTIBLE_HXX

namespace libport
{
  inline Destructible::Lock::Lock(Destructible& parent)
    : parent_(parent)
  {
    parent_.take();
  }

  inline Destructible::Lock::~Lock()
  {
    parent_.release();
  }

  inline Destructible::Destructible()
    :destructionPending_(false)
     , destructionEnacted_(false)
     ,  count_(0)
  {
  }

  inline Destructible::DestructionLock
  Destructible::getDestructionLock()
  {
    return DestructionLock(new Lock(*this));
  }

  inline bool
  Destructible::pendingDestruction()
  {
    return destructionPending_;
  }

  inline void
  Destructible::destroy()
  {
    //Cant use BlockLock: must unlock before doDestroy.
    threadLock_.lock();
    destructionPending_ = true;
    if (!count_ && !destructionEnacted_)
    {
      destructionEnacted_ = true;
      threadLock_.unlock();
      doDestroy();
    }
    else
      threadLock_.unlock();
  }

  inline Destructible::~Destructible()
  {
  }

  inline void
  Destructible::doDestroy()
  {
    delete this;
  }

  inline void
  Destructible::take()
  {
    count_++;
  }

  inline void
  Destructible::release()
  {
    // Cant use blocklock: we must unlock before calling doDestroy.
    threadLock_.lock();
    LIBPORT_COND_UPDATE(canDestroy_, count_--, !count_);
    if (!count_ && destructionPending_ && !destructionEnacted_)
    {
      destructionEnacted_ = true;
      threadLock_.unlock();
      doDestroy();
    }
    else
      threadLock_.unlock();
  }

  inline void
  Destructible::wasDestroyed()
  {
    destructionEnacted_ = true;<commit_msg>Destructible: Fix a race condition.<commit_after>/*
 * Copyright (C) 2009, <NAME>.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */
#ifndef LIBPORT_DESTRUCTIBLE_HXX
# define LIBORT_DESTRUCTIBLE_HXX

namespace libport
{
  inline Destructible::Lock::Lock(Destructible& parent)
    : parent_(parent)
  {
    parent_.take();
  }

  inline Destructible::Lock::~Lock()
  {
    parent_.release();
  }

  inline Destructible::Destructible()
    :destructionPending_(false)
     , destructionEnacted_(false)
     ,  count_(0)
  {
  }

  inline Destructible::DestructionLock
  Destructible::getDestructionLock()
  {
    return DestructionLock(new Lock(*this));
  }

  inline bool
  Destructible::pendingDestruction()
  {
    return destructionPending_;
  }

  inline void
  Destructible::destroy()
  {
    //Cant use BlockLock: must unlock before doDestroy.
    threadLock_.lock();
    destructionPending_ = true;
    if (!count_ && !destructionEnacted_)
    {
      destructionEnacted_ = true;
      threadLock_.unlock();
      doDestroy();
    }
    else
      threadLock_.unlock();
  }

  inline Destructible::~Destructible()
  {
  }

  inline void
  Destructible::doDestroy()
  {
    delete this;
  }

  inline void
  Destructible::take()
  {
    LIBPORT_COND_UPDATE(canDestroy_, count_++, false);
  }

  inline void
  Destructible::release()
  {
    // Cant use blocklock: we must unlock before calling doDestroy.
    threadLock_.lock();
    LIBPORT_COND_UPDATE(canDestroy_, count_--, !count_);
    if (!count_ && destructionPending_ && !destructionEnacted_)
    {
      destructionEnacted_ = true;
      threadLock_.unlock();
      doDestroy();
    }
    else
      threadLock_.unlock();
  }

  inline void
  Destructible::wasDestroyed()
  {
    destructionEnacted_ = true;
{'fraction_non_alphanumeric': 0.107982433479721, 'fraction_numerical': 0.0025833118057349523, 'mean_word_length': 3.273730684326711, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1762610', 'n_tokens_mistral': 1226, 'n_tokens_neox': 1199, 'n_words': 275}