<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/waitable_event_watcher.h"

#include "base/condition_variable.h"
#include "base/lock.h"
#include "base/message_loop.h"
#include "base/waitable_event.h"

namespace base {

// -----------------------------------------------------------------------------
// WaitableEventWatcher (async waits).
//
// The basic design is that we add an AsyncWaiter to the wait-list of the event.
// That AsyncWaiter has a pointer to MessageLoop, and a Task to be posted to it.
// The MessageLoop ends up running the task, which calls the delegate.
//
// Since the wait can be canceled, we have a thread-safe Flag object which is
// set when the wait has been canceled. At each stage in the above, we check the
// flag before going onto the next stage. Since the wait may only be canceled in
// the MessageLoop which runs the Task, we are assured that the delegate cannot
// be called after canceling...

// -----------------------------------------------------------------------------
// A thread-safe, reference-counted, write-once flag.
// -----------------------------------------------------------------------------
class Flag : public RefCountedThreadSafe<Flag> {
 public:
  Flag() { flag_ = false; }

  void Set() {
    AutoLock locked(lock_);
    flag_ = true;
  }

  bool value() const {
    AutoLock locked(lock_);
    return flag_;
  }

 private:
  mutable Lock lock_;
  bool flag_;
};

// -----------------------------------------------------------------------------
// This is an asynchronous waiter which posts a task to a MessageLoop when
// fired. An AsyncWaiter may only be in a single wait-list.
// -----------------------------------------------------------------------------
class AsyncWaiter : public WaitableEvent::Waiter {
 public:
  AsyncWaiter(MessageLoop* message_loop, Task* task, Flag* flag)
      : message_loop_(message_loop),
        cb_task_(task),
        flag_(flag) { }

  bool Fire(WaitableEvent* event) {
    if (flag_->value()) {
      // If the callback has been canceled, we don't enqueue the task, we just
      // delete it instead.
      delete cb_task_;
    } else {
      message_loop_->PostTask(FROM_HERE, cb_task_);
    }

    // We are removed from the wait-list by the WaitableEvent itself. It only
    // remains to delete ourselves.
    delete this;

    // We can always return true because an AsyncWaiter is never in two
    // different wait-lists at the same time.
    return true;
  }

  // See StopWatching for discussion
  bool Compare(void* tag) {
    return tag == flag_.get();
  }

 private:
  MessageLoop *const message_loop_;
  Task *const cb_task_;
  scoped_refptr<Flag> flag_;
};

// -----------------------------------------------------------------------------
// For async waits we need to make a callback in a MessageLoop thread. We do
// this by posting this task, which calls the delegate and keeps track of when
// the event is canceled.
// -----------------------------------------------------------------------------
class AsyncCallbackTask : public Task {
 public:
  AsyncCallbackTask(Flag* flag, WaitableEventWatcher::Delegate* delegate,
                    WaitableEvent* event)
      : flag_(flag),
        delegate_(delegate),
        event_(event) {
  }

  void Run() {
    // Runs in MessageLoop thread.
    if (!flag_->value()) {
      // This is to let the WaitableEventWatcher know that the event has occured
      // because it needs to be able to return NULL from GetWatchedObject
      flag_->Set();
      delegate_->OnWaitableEventSignaled(event_);
    }

    // We are deleted by the MessageLoop
  }

 private:
  scoped_refptr<Flag> flag_;
  WaitableEventWatcher::Delegate *const delegate_;
  WaitableEvent *const event_;
};

WaitableEventWatcher::WaitableEventWatcher()
    : event_(NULL),
      message_loop_(NULL),
      cancel_flag_(NULL),<commit_msg>Coverity: uninitialized member in posix WaitableEventWatcher constructor.<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/waitable_event_watcher.h"

#include "base/condition_variable.h"
#include "base/lock.h"
#include "base/message_loop.h"
#include "base/waitable_event.h"

namespace base {

// -----------------------------------------------------------------------------
// WaitableEventWatcher (async waits).
//
// The basic design is that we add an AsyncWaiter to the wait-list of the event.
// That AsyncWaiter has a pointer to MessageLoop, and a Task to be posted to it.
// The MessageLoop ends up running the task, which calls the delegate.
//
// Since the wait can be canceled, we have a thread-safe Flag object which is
// set when the wait has been canceled. At each stage in the above, we check the
// flag before going onto the next stage. Since the wait may only be canceled in
// the MessageLoop which runs the Task, we are assured that the delegate cannot
// be called after canceling...

// -----------------------------------------------------------------------------
// A thread-safe, reference-counted, write-once flag.
// -----------------------------------------------------------------------------
class Flag : public RefCountedThreadSafe<Flag> {
 public:
  Flag() { flag_ = false; }

  void Set() {
    AutoLock locked(lock_);
    flag_ = true;
  }

  bool value() const {
    AutoLock locked(lock_);
    return flag_;
  }

 private:
  mutable Lock lock_;
  bool flag_;
};

// -----------------------------------------------------------------------------
// This is an asynchronous waiter which posts a task to a MessageLoop when
// fired. An AsyncWaiter may only be in a single wait-list.
// -----------------------------------------------------------------------------
class AsyncWaiter : public WaitableEvent::Waiter {
 public:
  AsyncWaiter(MessageLoop* message_loop, Task* task, Flag* flag)
      : message_loop_(message_loop),
        cb_task_(task),
        flag_(flag) { }

  bool Fire(WaitableEvent* event) {
    if (flag_->value()) {
      // If the callback has been canceled, we don't enqueue the task, we just
      // delete it instead.
      delete cb_task_;
    } else {
      message_loop_->PostTask(FROM_HERE, cb_task_);
    }

    // We are removed from the wait-list by the WaitableEvent itself. It only
    // remains to delete ourselves.
    delete this;

    // We can always return true because an AsyncWaiter is never in two
    // different wait-lists at the same time.
    return true;
  }

  // See StopWatching for discussion
  bool Compare(void* tag) {
    return tag == flag_.get();
  }

 private:
  MessageLoop *const message_loop_;
  Task *const cb_task_;
  scoped_refptr<Flag> flag_;
};

// -----------------------------------------------------------------------------
// For async waits we need to make a callback in a MessageLoop thread. We do
// this by posting this task, which calls the delegate and keeps track of when
// the event is canceled.
// -----------------------------------------------------------------------------
class AsyncCallbackTask : public Task {
 public:
  AsyncCallbackTask(Flag* flag, WaitableEventWatcher::Delegate* delegate,
                    WaitableEvent* event)
      : flag_(flag),
        delegate_(delegate),
        event_(event) {
  }

  void Run() {
    // Runs in MessageLoop thread.
    if (!flag_->value()) {
      // This is to let the WaitableEventWatcher know that the event has occured
      // because it needs to be able to return NULL from GetWatchedObject
      flag_->Set();
      delegate_->OnWaitableEventSignaled(event_);
    }

    // We are deleted by the MessageLoop
  }

 private:
  scoped_refptr<Flag> flag_;
  WaitableEventWatcher::Delegate *const delegate_;
  WaitableEvent *const event_;
};

WaitableEventWatcher::WaitableEventWatcher()
    : event_(NULL),
      message_loop_(NULL),
      cancel_flag_(NULL),
      waiter_(NULL),
{'fraction_non_alphanumeric': 0.21313491575451973, 'fraction_numerical': 0.001967777641126553, 'mean_word_length': 1.8623724040830694, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 19, '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': '4921357', 'n_tokens_mistral': 2101, 'n_tokens_neox': 2038, 'n_words': 804}