13345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Copyright (c) 2010 The Chromium Authors. All rights reserved. 206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch// Use of this source code is governed by a BSD-style license that can be 306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch// found in the LICENSE file. 406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch#include <iosfwd> 606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch#include <sstream> 706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch#include <string> 806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch#include <vector> 906741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 1006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch#include "base/basictypes.h" 1106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch#include "base/message_loop.h" 1206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch#include "base/port.h" 133f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/platform_thread.h" 1406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch#include "build/build_config.h" 1506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch#include "chrome/common/deprecated/event_sys-inl.h" 1606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch#include "testing/gtest/include/gtest/gtest.h" 1706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 1806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdochnamespace { 1906741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 2006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdochclass Pair; 2106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 2206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdochstruct TestEvent { 2306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch Pair* source; 2406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch enum { 2506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch A_CHANGED, B_CHANGED, PAIR_BEING_DELETED, 2606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch } what_happened; 2706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch int old_value; 2806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch}; 2906741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 3006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdochstruct TestEventTraits { 3106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch typedef TestEvent EventType; 3206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch static bool IsChannelShutdownEvent(const TestEvent& event) { 3306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch return TestEvent::PAIR_BEING_DELETED == event.what_happened; 3406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch } 3506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch}; 3606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 3706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdochclass Pair { 3806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch public: 3906741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch typedef EventChannel<TestEventTraits> Channel; 40731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick explicit Pair(const std::string& name) : name_(name), a_(0), b_(0) { 4106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch TestEvent shutdown = { this, TestEvent::PAIR_BEING_DELETED, 0 }; 4206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch event_channel_ = new Channel(shutdown); 4306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch } 4406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch ~Pair() { 4506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch delete event_channel_; 4606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch } 4706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch void set_a(int n) { 4806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch TestEvent event = { this, TestEvent::A_CHANGED, a_ }; 4906741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch a_ = n; 5006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch event_channel_->NotifyListeners(event); 5106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch } 5206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch void set_b(int n) { 5306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch TestEvent event = { this, TestEvent::B_CHANGED, b_ }; 5406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch b_ = n; 5506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch event_channel_->NotifyListeners(event); 5606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch } 5706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch int a() const { return a_; } 5806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch int b() const { return b_; } 59731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const std::string& name() { return name_; } 6006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch Channel* event_channel() const { return event_channel_; } 6106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 6206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch protected: 63731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const std::string name_; 6406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch int a_; 6506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch int b_; 6606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch Channel* event_channel_; 6706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch}; 6806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 6906741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdochclass EventLogger { 7006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch public: 71731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick explicit EventLogger(std::ostream* out) : out_(out) { } 7206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch ~EventLogger() { 7306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch for (Hookups::iterator i = hookups_.begin(); i != hookups_.end(); ++i) 7406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch delete *i; 7506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch } 7606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 77731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick void Hookup(const std::string name, Pair::Channel* channel) { 7806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch hookups_.push_back(NewEventListenerHookup(channel, this, 7906741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch &EventLogger::HandlePairEvent, 8006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch name)); 8106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch } 8206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 83731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick void HandlePairEvent(const std::string& name, const TestEvent& event) { 8406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch const char* what_changed = NULL; 8506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch int new_value = 0; 8606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch Hookups::iterator dead; 8706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch switch (event.what_happened) { 8806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch case TestEvent::A_CHANGED: 8906741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch what_changed = "A"; 9006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch new_value = event.source->a(); 9106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch break; 9206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch case TestEvent::B_CHANGED: 9306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch what_changed = "B"; 9406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch new_value = event.source->b(); 9506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch break; 9606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch case TestEvent::PAIR_BEING_DELETED: 97731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick *out_ << name << " heard " << event.source->name() << " being deleted." 98731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick << std::endl; 9906741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch return; 10006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch default: 10106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch FAIL() << "Bad event.what_happened: " << event.what_happened; 10206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch break; 10306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch } 104731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick *out_ << name << " heard " << event.source->name() << "'s " << what_changed 105731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick << " change from " << event.old_value 106731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick << " to " << new_value << std::endl; 10706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch } 10806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 109731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick typedef std::vector<EventListenerHookup*> Hookups; 11006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch Hookups hookups_; 111731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::ostream* out_; 11206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch}; 11306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 11406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdochconst char golden_result[] = "Larry heard Sally's B change from 0 to 2\n" 11506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch"Larry heard Sally's A change from 1 to 3\n" 11606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch"Lewis heard Sam's B change from 0 to 5\n" 11706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch"Larry heard Sally's A change from 3 to 6\n" 11806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch"Larry heard Sally being deleted.\n"; 11906741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 12006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen MurdochTEST(EventSys, Basic) { 12106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch Pair sally("Sally"), sam("Sam"); 12206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch sally.set_a(1); 123731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::stringstream log; 124731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick EventLogger logger(&log); 12506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch logger.Hookup("Larry", sally.event_channel()); 12606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch sally.set_b(2); 12706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch sally.set_a(3); 12806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch sam.set_a(4); 12906741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch logger.Hookup("Lewis", sam.event_channel()); 13006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch sam.set_b(5); 13106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch sally.set_a(6); 13206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch // Test that disconnect within callback doesn't deadlock. 13306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch TestEvent event = {&sally, TestEvent::PAIR_BEING_DELETED, 0 }; 13406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch sally.event_channel()->NotifyListeners(event); 13506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch sally.set_a(7); 13606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch ASSERT_EQ(log.str(), golden_result); 13706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch} 13806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 13906741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 14006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch// This goes pretty far beyond the normal use pattern, so don't use 14106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch// ThreadTester as an example of what to do. 14206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdochclass ThreadTester : public EventListener<TestEvent>, 1433f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen public base::PlatformThread::Delegate { 14406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch public: 14506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch explicit ThreadTester(Pair* pair) 14606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch : pair_(pair), remove_event_(&remove_event_mutex_), 14706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch remove_event_bool_(false), completed_(false) { 14806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch pair_->event_channel()->AddListener(this); 14906741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch } 15006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch ~ThreadTester() { 15106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch pair_->event_channel()->RemoveListener(this); 15206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch for (size_t i = 0; i < threads_.size(); i++) { 1533f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen base::PlatformThread::Join(threads_[i].thread); 15406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch } 15506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch } 15606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 15706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch struct ThreadInfo { 1583f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen base::PlatformThreadHandle thread; 15906741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch }; 16006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 16106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch struct ThreadArgs { 1623f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen base::ConditionVariable* thread_running_cond; 1633f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen base::Lock* thread_running_mutex; 16406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch bool thread_running; 16506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch }; 16606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 16706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch void Go() { 1683f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen base::Lock thread_running_mutex; 1693f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen base::ConditionVariable thread_running_cond(&thread_running_mutex); 17006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch ThreadArgs args; 17106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch ThreadInfo info; 17206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch args.thread_running_cond = &(thread_running_cond); 17306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch args.thread_running_mutex = &(thread_running_mutex); 17406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch args.thread_running = false; 17506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch args_ = args; 1763f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen ASSERT_TRUE(base::PlatformThread::Create(0, this, &info.thread)); 17706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch thread_running_mutex.Acquire(); 17806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch while ((args_.thread_running) == false) { 17906741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch thread_running_cond.Wait(); 18006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch } 18106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch thread_running_mutex.Release(); 18206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch threads_.push_back(info); 18306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch } 18406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 18506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch // PlatformThread::Delegate methods. 18606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch virtual void ThreadMain() { 18706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch // Make sure each thread gets a current MessageLoop in TLS. 18806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch // This test should use chrome threads for testing, but I'll leave it like 18906741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch // this for the moment since it requires a big chunk of rewriting and I 19006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch // want the test passing while I checkpoint my CL. Technically speaking, 19106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch // there should be no functional difference. 19206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch MessageLoop message_loop; 19306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch args_.thread_running_mutex->Acquire(); 19406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch args_.thread_running = true; 19506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch args_.thread_running_cond->Signal(); 19606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch args_.thread_running_mutex->Release(); 19706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 19806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch remove_event_mutex_.Acquire(); 19906741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch while (remove_event_bool_ == false) { 20006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch remove_event_.Wait(); 20106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch } 20206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch remove_event_mutex_.Release(); 20306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 20406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch // Normally, you'd just delete the hookup. This is very bad style, but 20506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch // necessary for the test. 20606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch pair_->event_channel()->RemoveListener(this); 20706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 20806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch completed_mutex_.Acquire(); 20906741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch completed_ = true; 21006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch completed_mutex_.Release(); 21106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch } 21206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 21306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch void HandleEvent(const TestEvent& event) { 21406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch remove_event_mutex_.Acquire(); 21506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch remove_event_bool_ = true; 21606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch remove_event_.Broadcast(); 21706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch remove_event_mutex_.Release(); 21806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 2193f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen base::PlatformThread::YieldCurrentThread(); 22006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 22106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch completed_mutex_.Acquire(); 22206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch if (completed_) 22306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch FAIL() << "A test thread exited too early."; 22406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch completed_mutex_.Release(); 22506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch } 22606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 22706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch Pair* pair_; 2283f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen base::ConditionVariable remove_event_; 2293f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen base::Lock remove_event_mutex_; 23006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch bool remove_event_bool_; 2313f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen base::Lock completed_mutex_; 23206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch bool completed_; 233731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::vector<ThreadInfo> threads_; 23406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch ThreadArgs args_; 23506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch}; 23606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 23706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen MurdochTEST(EventSys, Multithreaded) { 23806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch Pair sally("Sally"); 23906741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch ThreadTester a(&sally); 24006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch for (int i = 0; i < 3; ++i) 24106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch a.Go(); 24206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch sally.set_b(99); 24306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch} 24406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 24506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdochclass HookupDeleter { 24606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch public: 24706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch void HandleEvent(const TestEvent& event) { 24806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch delete hookup_; 24906741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch hookup_ = NULL; 25006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch } 25106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch EventListenerHookup* hookup_; 25206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch}; 25306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 25406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen MurdochTEST(EventSys, InHandlerDeletion) { 25506741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch Pair sally("Sally"); 25606741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch HookupDeleter deleter; 25706741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch deleter.hookup_ = NewEventListenerHookup(sally.event_channel(), 25806741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch &deleter, 25906741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch &HookupDeleter::HandleEvent); 26006741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch sally.set_a(1); 26106741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch ASSERT_TRUE(NULL == deleter.hookup_); 26206741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch} 26306741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch 26406741cbc25cd4227a9fba40dfd0273bfcc1a587aBen Murdoch} // namespace 265