diff options
author | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-13 19:18:52 +0000 |
---|---|---|
committer | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-07-13 19:18:52 +0000 |
commit | 47a961c13f61cdbd00a7020a5a8173586a8ed892 (patch) | |
tree | a89ea8f0c81f5c74cb5bcaf852e4e83ab21fbc75 /ppapi | |
parent | 8367f7b3aab8365ed5e696e4720a2a416d956d0a (diff) | |
download | chromium_src-47a961c13f61cdbd00a7020a5a8173586a8ed892.zip chromium_src-47a961c13f61cdbd00a7020a5a8173586a8ed892.tar.gz chromium_src-47a961c13f61cdbd00a7020a5a8173586a8ed892.tar.bz2 |
Add support for threadsafe completion callback factory.
This also makes the default be threadsafe. The old factory wasn't threadsafe even to the extent claimed in the header which was causing hangs in plugins
BUG=136284
Review URL: https://chromiumcodereview.appspot.com/10696157
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@146611 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi')
33 files changed, 511 insertions, 186 deletions
diff --git a/ppapi/cpp/instance.h b/ppapi/cpp/instance.h index 838d97b..5e7931c 100644 --- a/ppapi/cpp/instance.h +++ b/ppapi/cpp/instance.h @@ -17,6 +17,11 @@ #include "ppapi/cpp/instance_handle.h" #include "ppapi/cpp/view.h" +// Windows defines 'PostMessage', so we have to undef it. +#ifdef PostMessage +#undef PostMessage +#endif + struct PP_InputEvent; /// The C++ interface to the Pepper API. diff --git a/ppapi/cpp/websocket.h b/ppapi/cpp/websocket.h index a34fdb7..0c72dc0 100644 --- a/ppapi/cpp/websocket.h +++ b/ppapi/cpp/websocket.h @@ -12,6 +12,11 @@ /// This file defines the WebSocket interface providing bi-directional, /// full-duplex, communications over a single TCP socket. +// Windows headers will redefine SendMessage. +#ifdef SendMessage +#undef SendMessage +#endif + namespace pp { class CompletionCallback; diff --git a/ppapi/examples/audio_input/audio_input.cc b/ppapi/examples/audio_input/audio_input.cc index d597b76..a216d54 100644 --- a/ppapi/examples/audio_input/audio_input.cc +++ b/ppapi/examples/audio_input/audio_input.cc @@ -20,6 +20,12 @@ #include "ppapi/cpp/size.h" #include "ppapi/utility/completion_callback_factory.h" +// When compiling natively on Windows, PostMessage can be #define-d to +// something else. +#ifdef PostMessage +#undef PostMessage +#endif + class MyInstance : public pp::Instance { public: explicit MyInstance(PP_Instance instance) diff --git a/ppapi/examples/scripting/post_message.cc b/ppapi/examples/scripting/post_message.cc index 24f7927..636a7a8 100644 --- a/ppapi/examples/scripting/post_message.cc +++ b/ppapi/examples/scripting/post_message.cc @@ -8,6 +8,12 @@ #include "ppapi/cpp/module.h" #include "ppapi/cpp/var.h" +// When compiling natively on Windows, PostMessage can be #define-d to +// something else. +#ifdef PostMessage +#undef PostMessage +#endif + // This is a simple C++ Pepper plugin that demonstrates HandleMessage and // PostMessage. diff --git a/ppapi/examples/url_loader/streaming.cc b/ppapi/examples/url_loader/streaming.cc index 80ee4f0..18efe68 100644 --- a/ppapi/examples/url_loader/streaming.cc +++ b/ppapi/examples/url_loader/streaming.cc @@ -18,6 +18,12 @@ #include "ppapi/cpp/url_response_info.h" #include "ppapi/utility/completion_callback_factory.h" +// When compiling natively on Windows, PostMessage can be #define-d to +// something else. +#ifdef PostMessage +#undef PostMessage +#endif + // Buffer size for reading network data. const int kBufSize = 1024; diff --git a/ppapi/examples/video_capture/video_capture.cc b/ppapi/examples/video_capture/video_capture.cc index 07239c6..25d2ef0 100644 --- a/ppapi/examples/video_capture/video_capture.cc +++ b/ppapi/examples/video_capture/video_capture.cc @@ -25,6 +25,12 @@ #include "ppapi/lib/gl/include/GLES2/gl2.h" #include "ppapi/utility/completion_callback_factory.h" +// When compiling natively on Windows, PostMessage can be #define-d to +// something else. +#ifdef PostMessage +#undef PostMessage +#endif + // Assert |context_| isn't holding any GL Errors. Done as a macro instead of a // function to preserve line number information in the failure message. #define assertNoGLError() \ diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h index 9b48e1f..90b93b7 100644 --- a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h +++ b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h @@ -39,26 +39,6 @@ class Plugin; class PnaclCoordinator; class PnaclTranslateThread; -// A thread safe reference counting class Needed for CompletionCallbackFactory -// in PnaclCoordinator. -class PnaclRefCount { - public: - PnaclRefCount() : ref_(0) { NaClXMutexCtor(&mu_); } - ~PnaclRefCount() { NaClMutexDtor(&mu_); } - int32_t AddRef() { - nacl::MutexLocker ml(&mu_); - return ++ref_; - } - int32_t Release() { - nacl::MutexLocker ml(&mu_); - return --ref_; - } - - private: - int32_t ref_; - struct NaClMutex mu_; -}; - // A class invoked by Plugin to handle PNaCl client-side translation. // Usage: // (1) Invoke the factory method, e.g., @@ -205,10 +185,9 @@ class PnaclCoordinator: public CallbackSource<FileStreamData> { Plugin* plugin_; pp::CompletionCallback translate_notify_callback_; - // PnaclRefCount is only needed to support file lookups. - // TODO(sehr): remove this when file lookup is through ReverseService. + // Threadsafety is required to support file lookups. pp::CompletionCallbackFactory<PnaclCoordinator, - PnaclRefCount> callback_factory_; + pp::ThreadSafeThreadTraits> callback_factory_; // Nexe from the final native Link. nacl::scoped_ptr<nacl::DescWrapper> translated_fd_; diff --git a/ppapi/ppapi_proxy.gypi b/ppapi/ppapi_proxy.gypi index e37c45e..7a21f15 100644 --- a/ppapi/ppapi_proxy.gypi +++ b/ppapi/ppapi_proxy.gypi @@ -143,6 +143,7 @@ 'proxy/proxy_array_output.h', 'proxy/proxy_channel.cc', 'proxy/proxy_channel.h', + 'proxy/proxy_completion_callback_factory.h', 'proxy/proxy_module.cc', 'proxy/proxy_module.h', 'proxy/proxy_object_var.cc', diff --git a/ppapi/ppapi_sources.gypi b/ppapi/ppapi_sources.gypi index 1e5904a..c5ee4a4 100644 --- a/ppapi/ppapi_sources.gypi +++ b/ppapi/ppapi_sources.gypi @@ -300,13 +300,15 @@ # Utility sources. 'utility/completion_callback_factory.h', - 'utility/non_thread_safe_ref_count.h', + 'utility/completion_callback_factory_thread_traits.h', 'utility/graphics/paint_aggregator.cc', 'utility/graphics/paint_aggregator.h', 'utility/graphics/paint_manager.cc', 'utility/graphics/paint_manager.h', 'utility/private/network_list_observer_private.cc', 'utility/private/network_list_observer_private.h', + 'utility/threading/lock.cc', + 'utility/threading/lock.h', 'utility/threading/simple_thread.cc', 'utility/threading/simple_thread.h', 'utility/websocket/websocket_api.cc', diff --git a/ppapi/proxy/ppb_audio_input_proxy.h b/ppapi/proxy/ppb_audio_input_proxy.h index 61125c6..f1fac75 100644 --- a/ppapi/proxy/ppb_audio_input_proxy.h +++ b/ppapi/proxy/ppb_audio_input_proxy.h @@ -16,7 +16,7 @@ #include "ppapi/c/dev/ppb_audio_input_dev.h" #include "ppapi/c/ppb_audio_config.h" #include "ppapi/proxy/interface_proxy.h" -#include "ppapi/proxy/proxy_non_thread_safe_ref_count.h" +#include "ppapi/proxy/proxy_completion_callback_factory.h" #include "ppapi/utility/completion_callback_factory.h" namespace ppapi { @@ -85,8 +85,7 @@ class PPB_AudioInput_Proxy : public InterfaceProxy { base::SharedMemoryHandle* foreign_shared_memory_handle, uint32_t* shared_memory_length); - pp::CompletionCallbackFactory<PPB_AudioInput_Proxy, - ProxyNonThreadSafeRefCount> callback_factory_; + ProxyCompletionCallbackFactory<PPB_AudioInput_Proxy> callback_factory_; DISALLOW_COPY_AND_ASSIGN(PPB_AudioInput_Proxy); }; diff --git a/ppapi/proxy/ppb_audio_proxy.h b/ppapi/proxy/ppb_audio_proxy.h index d8fe9a0..b516925 100644 --- a/ppapi/proxy/ppb_audio_proxy.h +++ b/ppapi/proxy/ppb_audio_proxy.h @@ -16,7 +16,7 @@ #include "ppapi/c/ppb_audio.h" #include "ppapi/c/ppb_audio_config.h" #include "ppapi/proxy/interface_proxy.h" -#include "ppapi/proxy/proxy_non_thread_safe_ref_count.h" +#include "ppapi/proxy/proxy_completion_callback_factory.h" #include "ppapi/utility/completion_callback_factory.h" namespace ppapi { @@ -74,8 +74,7 @@ class PPB_Audio_Proxy : public InterfaceProxy { base::SharedMemoryHandle* foreign_shared_memory_handle, uint32_t* shared_memory_length); - pp::CompletionCallbackFactory<PPB_Audio_Proxy, - ProxyNonThreadSafeRefCount> callback_factory_; + ProxyCompletionCallbackFactory<PPB_Audio_Proxy> callback_factory_; DISALLOW_COPY_AND_ASSIGN(PPB_Audio_Proxy); }; diff --git a/ppapi/proxy/ppb_broker_proxy.h b/ppapi/proxy/ppb_broker_proxy.h index a04903c7..5bc195a 100644 --- a/ppapi/proxy/ppb_broker_proxy.h +++ b/ppapi/proxy/ppb_broker_proxy.h @@ -9,7 +9,7 @@ #include "ipc/ipc_platform_file.h" #include "ppapi/c/pp_instance.h" #include "ppapi/proxy/interface_proxy.h" -#include "ppapi/proxy/proxy_non_thread_safe_ref_count.h" +#include "ppapi/proxy/proxy_completion_callback_factory.h" #include "ppapi/utility/completion_callback_factory.h" namespace ppapi { @@ -41,8 +41,7 @@ class PPB_Broker_Proxy : public InterfaceProxy { void ConnectCompleteInHost(int32_t result, const ppapi::HostResource& host_resource); - pp::CompletionCallbackFactory<PPB_Broker_Proxy, - ProxyNonThreadSafeRefCount> callback_factory_; + ProxyCompletionCallbackFactory<PPB_Broker_Proxy> callback_factory_; }; } // namespace proxy diff --git a/ppapi/proxy/ppb_file_chooser_proxy.h b/ppapi/proxy/ppb_file_chooser_proxy.h index 825d7c9..1dc0921 100644 --- a/ppapi/proxy/ppb_file_chooser_proxy.h +++ b/ppapi/proxy/ppb_file_chooser_proxy.h @@ -12,7 +12,7 @@ #include "ppapi/c/pp_instance.h" #include "ppapi/proxy/interface_proxy.h" #include "ppapi/proxy/proxy_array_output.h" -#include "ppapi/proxy/proxy_non_thread_safe_ref_count.h" +#include "ppapi/proxy/proxy_completion_callback_factory.h" #include "ppapi/proxy/serialized_var.h" #include "ppapi/thunk/ppb_file_chooser_api.h" #include "ppapi/cpp/output_traits.h" @@ -64,8 +64,7 @@ class PPB_FileChooser_Proxy : public InterfaceProxy { scoped_refptr<RefCountedArrayOutputAdapter<PP_Resource> > output, HostResource chooser); - pp::CompletionCallbackFactory<PPB_FileChooser_Proxy, - ProxyNonThreadSafeRefCount> callback_factory_; + ProxyCompletionCallbackFactory<PPB_FileChooser_Proxy> callback_factory_; DISALLOW_COPY_AND_ASSIGN(PPB_FileChooser_Proxy); }; diff --git a/ppapi/proxy/ppb_file_io_proxy.h b/ppapi/proxy/ppb_file_io_proxy.h index 86d822c..10e5313 100644 --- a/ppapi/proxy/ppb_file_io_proxy.h +++ b/ppapi/proxy/ppb_file_io_proxy.h @@ -10,7 +10,7 @@ #include "base/basictypes.h" #include "ppapi/c/pp_file_info.h" #include "ppapi/proxy/interface_proxy.h" -#include "ppapi/proxy/proxy_non_thread_safe_ref_count.h" +#include "ppapi/proxy/proxy_completion_callback_factory.h" #include "ppapi/utility/completion_callback_factory.h" namespace ppapi { @@ -82,8 +82,7 @@ class PPB_FileIO_Proxy : public InterfaceProxy { void ReadCallbackCompleteInHost(int32_t pp_error, const HostResource& host_resource, std::string* data); - pp::CompletionCallbackFactory<PPB_FileIO_Proxy, - ProxyNonThreadSafeRefCount> callback_factory_; + ProxyCompletionCallbackFactory<PPB_FileIO_Proxy> callback_factory_; DISALLOW_COPY_AND_ASSIGN(PPB_FileIO_Proxy); }; diff --git a/ppapi/proxy/ppb_file_ref_proxy.h b/ppapi/proxy/ppb_file_ref_proxy.h index d15536e..64febfa 100644 --- a/ppapi/proxy/ppb_file_ref_proxy.h +++ b/ppapi/proxy/ppb_file_ref_proxy.h @@ -12,7 +12,7 @@ #include "ppapi/c/pp_resource.h" #include "ppapi/c/pp_time.h" #include "ppapi/proxy/interface_proxy.h" -#include "ppapi/proxy/proxy_non_thread_safe_ref_count.h" +#include "ppapi/proxy/proxy_completion_callback_factory.h" #include "ppapi/utility/completion_callback_factory.h" namespace ppapi { @@ -92,8 +92,7 @@ class PPB_FileRef_Proxy : public InterfaceProxy { const HostResource& host_resource, int callback_id); - pp::CompletionCallbackFactory<PPB_FileRef_Proxy, - ProxyNonThreadSafeRefCount> callback_factory_; + ProxyCompletionCallbackFactory<PPB_FileRef_Proxy> callback_factory_; DISALLOW_COPY_AND_ASSIGN(PPB_FileRef_Proxy); }; diff --git a/ppapi/proxy/ppb_file_system_proxy.h b/ppapi/proxy/ppb_file_system_proxy.h index 86eb48e..68197e7 100644 --- a/ppapi/proxy/ppb_file_system_proxy.h +++ b/ppapi/proxy/ppb_file_system_proxy.h @@ -13,7 +13,7 @@ #include "ppapi/c/pp_time.h" #include "ppapi/c/ppb_file_system.h" #include "ppapi/proxy/interface_proxy.h" -#include "ppapi/proxy/proxy_non_thread_safe_ref_count.h" +#include "ppapi/proxy/proxy_completion_callback_factory.h" #include "ppapi/utility/completion_callback_factory.h" namespace ppapi { @@ -51,8 +51,7 @@ class PPB_FileSystem_Proxy : public InterfaceProxy { void OpenCompleteInHost(int32_t result, const ppapi::HostResource& host_resource); - pp::CompletionCallbackFactory<PPB_FileSystem_Proxy, - ProxyNonThreadSafeRefCount> callback_factory_; + ProxyCompletionCallbackFactory<PPB_FileSystem_Proxy> callback_factory_; DISALLOW_COPY_AND_ASSIGN(PPB_FileSystem_Proxy); }; diff --git a/ppapi/proxy/ppb_flash_menu_proxy.h b/ppapi/proxy/ppb_flash_menu_proxy.h index 8c20774..b9eda00 100644 --- a/ppapi/proxy/ppb_flash_menu_proxy.h +++ b/ppapi/proxy/ppb_flash_menu_proxy.h @@ -6,7 +6,7 @@ #define PPAPI_PPB_FLASH_MENU_PROXY_H_ #include "ppapi/proxy/interface_proxy.h" -#include "ppapi/proxy/proxy_non_thread_safe_ref_count.h" +#include "ppapi/proxy/proxy_completion_callback_factory.h" #include "ppapi/utility/completion_callback_factory.h" struct PP_Flash_Menu; @@ -46,8 +46,7 @@ class PPB_Flash_Menu_Proxy : public InterfaceProxy { int32_t result); void SendShowACKToPlugin(int32_t result, ShowRequest* request); - pp::CompletionCallbackFactory<PPB_Flash_Menu_Proxy, - ProxyNonThreadSafeRefCount> callback_factory_; + ProxyCompletionCallbackFactory<PPB_Flash_Menu_Proxy> callback_factory_; }; } // namespace proxy diff --git a/ppapi/proxy/ppb_graphics_2d_proxy.h b/ppapi/proxy/ppb_graphics_2d_proxy.h index 45043ce..cf0a921 100644 --- a/ppapi/proxy/ppb_graphics_2d_proxy.h +++ b/ppapi/proxy/ppb_graphics_2d_proxy.h @@ -13,7 +13,7 @@ #include "ppapi/c/pp_size.h" #include "ppapi/c/pp_var.h" #include "ppapi/proxy/interface_proxy.h" -#include "ppapi/proxy/proxy_non_thread_safe_ref_count.h" +#include "ppapi/proxy/proxy_completion_callback_factory.h" #include "ppapi/shared_impl/host_resource.h" #include "ppapi/utility/completion_callback_factory.h" @@ -66,8 +66,7 @@ class PPB_Graphics2D_Proxy : public InterfaceProxy { void SendFlushACKToPlugin(int32_t result, const HostResource& graphics_2d); - pp::CompletionCallbackFactory<PPB_Graphics2D_Proxy, - ProxyNonThreadSafeRefCount> callback_factory_; + ProxyCompletionCallbackFactory<PPB_Graphics2D_Proxy> callback_factory_; DISALLOW_COPY_AND_ASSIGN(PPB_Graphics2D_Proxy); }; diff --git a/ppapi/proxy/ppb_graphics_3d_proxy.h b/ppapi/proxy/ppb_graphics_3d_proxy.h index 521d90e..d16053c 100644 --- a/ppapi/proxy/ppb_graphics_3d_proxy.h +++ b/ppapi/proxy/ppb_graphics_3d_proxy.h @@ -12,7 +12,7 @@ #include "ppapi/c/pp_graphics_3d.h" #include "ppapi/c/pp_instance.h" #include "ppapi/proxy/interface_proxy.h" -#include "ppapi/proxy/proxy_non_thread_safe_ref_count.h" +#include "ppapi/proxy/proxy_completion_callback_factory.h" #include "ppapi/shared_impl/ppb_graphics_3d_shared.h" #include "ppapi/shared_impl/resource.h" #include "ppapi/utility/completion_callback_factory.h" @@ -106,8 +106,7 @@ class PPB_Graphics3D_Proxy : public InterfaceProxy { void SendSwapBuffersACKToPlugin(int32_t result, const HostResource& context); - pp::CompletionCallbackFactory<PPB_Graphics3D_Proxy, - ProxyNonThreadSafeRefCount> callback_factory_; + ProxyCompletionCallbackFactory<PPB_Graphics3D_Proxy> callback_factory_; DISALLOW_COPY_AND_ASSIGN(PPB_Graphics3D_Proxy); }; diff --git a/ppapi/proxy/ppb_instance_proxy.h b/ppapi/proxy/ppb_instance_proxy.h index 20dd60d..e2ac4d7 100644 --- a/ppapi/proxy/ppb_instance_proxy.h +++ b/ppapi/proxy/ppb_instance_proxy.h @@ -10,7 +10,7 @@ #include "ppapi/c/pp_time.h" #include "ppapi/c/pp_var.h" #include "ppapi/proxy/interface_proxy.h" -#include "ppapi/proxy/proxy_non_thread_safe_ref_count.h" +#include "ppapi/proxy/proxy_completion_callback_factory.h" #include "ppapi/shared_impl/host_resource.h" #include "ppapi/shared_impl/ppb_instance_shared.h" #include "ppapi/thunk/ppb_instance_api.h" @@ -194,8 +194,7 @@ class PPB_Instance_Proxy : public InterfaceProxy, void MouseLockCompleteInHost(int32_t result, PP_Instance instance); - pp::CompletionCallbackFactory<PPB_Instance_Proxy, - ProxyNonThreadSafeRefCount> callback_factory_; + ProxyCompletionCallbackFactory<PPB_Instance_Proxy> callback_factory_; }; } // namespace proxy diff --git a/ppapi/proxy/ppb_url_loader_proxy.h b/ppapi/proxy/ppb_url_loader_proxy.h index 7dea1e8..5fd924d 100644 --- a/ppapi/proxy/ppb_url_loader_proxy.h +++ b/ppapi/proxy/ppb_url_loader_proxy.h @@ -14,7 +14,7 @@ #include "ppapi/c/ppb_url_loader.h" #include "ppapi/c/trusted/ppb_url_loader_trusted.h" #include "ppapi/proxy/interface_proxy.h" -#include "ppapi/proxy/proxy_non_thread_safe_ref_count.h" +#include "ppapi/proxy/proxy_completion_callback_factory.h" #include "ppapi/shared_impl/host_resource.h" #include "ppapi/utility/completion_callback_factory.h" @@ -86,8 +86,7 @@ class PPB_URLLoader_Proxy : public InterfaceProxy { // Handles callback for everything but reads. void OnCallback(int32_t result, const HostResource& resource); - pp::CompletionCallbackFactory<PPB_URLLoader_Proxy, - ProxyNonThreadSafeRefCount> callback_factory_; + ProxyCompletionCallbackFactory<PPB_URLLoader_Proxy> callback_factory_; // Valid only in the host, this lazily-initialized pointer indicates the // URLLoaderTrusted interface. diff --git a/ppapi/proxy/ppb_video_capture_proxy.h b/ppapi/proxy/ppb_video_capture_proxy.h index 2b86460..cf01875 100644 --- a/ppapi/proxy/ppb_video_capture_proxy.h +++ b/ppapi/proxy/ppb_video_capture_proxy.h @@ -10,7 +10,7 @@ #include "ppapi/c/pp_instance.h" #include "ppapi/proxy/interface_proxy.h" -#include "ppapi/proxy/proxy_non_thread_safe_ref_count.h" +#include "ppapi/proxy/proxy_completion_callback_factory.h" #include "ppapi/proxy/serialized_structs.h" #include "ppapi/shared_impl/ppb_device_ref_shared.h" #include "ppapi/utility/completion_callback_factory.h" @@ -64,8 +64,7 @@ class PPB_VideoCapture_Proxy : public InterfaceProxy { const ppapi::HostResource& resource); void OpenACKInHost(int32_t result, const ppapi::HostResource& resource); - pp::CompletionCallbackFactory<PPB_VideoCapture_Proxy, - ProxyNonThreadSafeRefCount> callback_factory_; + ProxyCompletionCallbackFactory<PPB_VideoCapture_Proxy> callback_factory_; DISALLOW_COPY_AND_ASSIGN(PPB_VideoCapture_Proxy); }; diff --git a/ppapi/proxy/ppb_video_decoder_proxy.h b/ppapi/proxy/ppb_video_decoder_proxy.h index 7461a1f..ffb259e 100644 --- a/ppapi/proxy/ppb_video_decoder_proxy.h +++ b/ppapi/proxy/ppb_video_decoder_proxy.h @@ -7,7 +7,7 @@ #include "ppapi/c/pp_instance.h" #include "ppapi/proxy/interface_proxy.h" -#include "ppapi/proxy/proxy_non_thread_safe_ref_count.h" +#include "ppapi/proxy/proxy_completion_callback_factory.h" #include "ppapi/shared_impl/ppb_video_decoder_shared.h" #include "ppapi/thunk/ppb_video_decoder_api.h" #include "ppapi/utility/completion_callback_factory.h" @@ -67,8 +67,7 @@ class PPB_VideoDecoder_Proxy : public InterfaceProxy { void OnMsgFlushACK(const ppapi::HostResource& decoder, int32_t result); void OnMsgResetACK(const ppapi::HostResource& decoder, int32_t result); - pp::CompletionCallbackFactory<PPB_VideoDecoder_Proxy, - ProxyNonThreadSafeRefCount> callback_factory_; + ProxyCompletionCallbackFactory<PPB_VideoDecoder_Proxy> callback_factory_; DISALLOW_COPY_AND_ASSIGN(PPB_VideoDecoder_Proxy); }; diff --git a/ppapi/proxy/proxy_completion_callback_factory.h b/ppapi/proxy/proxy_completion_callback_factory.h new file mode 100644 index 0000000..1221f43 --- /dev/null +++ b/ppapi/proxy/proxy_completion_callback_factory.h @@ -0,0 +1,87 @@ +// Copyright (c) 2012 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. + +#ifndef PPAPI_PROXY_PROXY_COMPLETION_CALLBACK_FACTORY_H_ +#define PPAPI_PROXY_PROXY_COMPLETION_CALLBACK_FACTORY_H_ + +#include "base/logging.h" +#include "base/message_loop.h" +#include "ppapi/cpp/completion_callback.h" +#include "ppapi/utility/completion_callback_factory.h" + +namespace ppapi { +namespace proxy { + +// This class is just like pp::NonThreadSafeThreadTraits but rather than using +// pp::Module::core (which doesn't exist), it uses Chrome threads which do. +class ProxyNonThreadSafeThreadTraits { + public: + class RefCount { + public: + RefCount() : ref_(0) { +#ifndef NDEBUG + message_loop_ = MessageLoop::current(); +#endif + } + + ~RefCount() { +#ifndef NDEBUG + DCHECK(message_loop_ == MessageLoop::current()); +#endif + } + + int32_t AddRef() { +#ifndef NDEBUG + DCHECK(message_loop_ == MessageLoop::current()); +#endif + return ++ref_; + } + + int32_t Release() { +#ifndef NDEBUG + DCHECK(message_loop_ == MessageLoop::current()); +#endif + DCHECK(ref_ > 0); + return --ref_; + } + + private: + int32_t ref_; +#ifndef NDEBUG + MessageLoop* message_loop_; +#endif + }; + + // No-op lock class. + class Lock { + public: + Lock() {} + ~Lock() {} + + void Acquire() {} + void Release() {} + }; + + // No-op AutoLock class. + class AutoLock { + public: + explicit AutoLock(Lock&) {} + ~AutoLock() {} + }; +}; + +template<typename T> +class ProxyCompletionCallbackFactory + : public pp::CompletionCallbackFactory<T, ProxyNonThreadSafeThreadTraits> { + public: + ProxyCompletionCallbackFactory() + : pp::CompletionCallbackFactory<T, ProxyNonThreadSafeThreadTraits>() {} + ProxyCompletionCallbackFactory(T* t) + : pp::CompletionCallbackFactory<T, ProxyNonThreadSafeThreadTraits>(t) {} +}; + +} // namespace proxy +} // namespace ppapi + +#endif // PPAPI_PROXY_PROXY_COMPLETION_CALLBACK_FACTORY_H_ diff --git a/ppapi/proxy/proxy_non_thread_safe_ref_count.h b/ppapi/proxy/proxy_non_thread_safe_ref_count.h deleted file mode 100644 index 855c87c..0000000 --- a/ppapi/proxy/proxy_non_thread_safe_ref_count.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2011 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. - -#ifndef PPAPI_PROXY_PROXY_NON_THREAD_SAFE_REF_COUNT_H_ -#define PPAPI_PROXY_PROXY_NON_THREAD_SAFE_REF_COUNT_H_ - -#include "base/message_loop.h" -#include "ppapi/cpp/completion_callback.h" - -namespace ppapi { -namespace proxy { - -// This class is just like ppapi/cpp/non_thread_safe_ref_count.h but rather -// than using pp::Module::core (which doesn't exist), it uses Chrome threads -// which do. -class ProxyNonThreadSafeRefCount { - public: - ProxyNonThreadSafeRefCount() : ref_(0) { -#ifndef NDEBUG - message_loop_ = MessageLoop::current(); -#endif - } - - ~ProxyNonThreadSafeRefCount() { - PP_DCHECK(message_loop_ == MessageLoop::current()); - } - - int32_t AddRef() { - PP_DCHECK(message_loop_ == MessageLoop::current()); - return ++ref_; - } - - int32_t Release() { - PP_DCHECK(message_loop_ == MessageLoop::current()); - return --ref_; - } - - private: - int32_t ref_; -#ifndef NDEBUG - MessageLoop* message_loop_; -#endif -}; - -} // namespace proxy -} // namespace ppapi - -#endif // PPAPI_PROXY_PROXY_NON_THREAD_SAFE_REF_COUNT_H_ diff --git a/ppapi/tests/all_cpp_includes.h b/ppapi/tests/all_cpp_includes.h index 6abe681..a85fa03 100644 --- a/ppapi/tests/all_cpp_includes.h +++ b/ppapi/tests/all_cpp_includes.h @@ -66,8 +66,11 @@ #include "ppapi/cpp/var.h" #include "ppapi/cpp/var_array_buffer.h" #include "ppapi/cpp/websocket.h" +#include "ppapi/utility/completion_callback_factory.h" +#include "ppapi/utility/completion_callback_factory_thread_traits.h" #include "ppapi/utility/graphics/paint_aggregator.h" #include "ppapi/utility/graphics/paint_manager.h" -#include "ppapi/utility/non_thread_safe_ref_count.h" +#include "ppapi/utility/threading/lock.h" +#include "ppapi/utility/threading/simple_thread.h" #endif // PPAPI_TESTS_ALL_CPP_INCLUDES_H_ diff --git a/ppapi/tests/testing_instance.h b/ppapi/tests/testing_instance.h index 1b2acbf..33ed21c 100644 --- a/ppapi/tests/testing_instance.h +++ b/ppapi/tests/testing_instance.h @@ -15,6 +15,11 @@ #include "ppapi/cpp/private/instance_private.h" #endif +// Windows defines 'PostMessage', so we have to undef it. +#ifdef PostMessage +#undef PostMessage +#endif + class TestCase; // How signaling works: diff --git a/ppapi/utility/completion_callback_factory.h b/ppapi/utility/completion_callback_factory.h index d521f4b..885767b 100644 --- a/ppapi/utility/completion_callback_factory.h +++ b/ppapi/utility/completion_callback_factory.h @@ -6,7 +6,7 @@ #define PPAPI_UTILITY_COMPLETION_CALLBACK_FACTORY_H_ #include "ppapi/cpp/completion_callback.h" -#include "ppapi/utility/non_thread_safe_ref_count.h" +#include "ppapi/utility/completion_callback_factory_thread_traits.h" /// @file /// This file defines the API to create CompletionCallback objects that are @@ -43,8 +43,8 @@ template <typename T> struct TypeUnwrapper<const T&> { /// factory. /// /// <strong>Note: </strong><code>CompletionCallbackFactory<T></code> isn't -/// thread safe, but you can make it more thread-friendly by passing a -/// thread-safe refcounting class as the second template element. However, it +/// thread safe, but it is somewhat thread-friendly when used with a +/// thread-safe traits class as the second template element. However, it /// only guarantees safety for creating a callback from another thread, the /// callback itself needs to execute on the same thread as the thread that /// creates/destroys the factory. With this restriction, it is safe to create @@ -185,7 +185,7 @@ template <typename T> struct TypeUnwrapper<const T&> { /// is to accept your output argument as a non-const reference and to swap() /// the argument with a vector of your own to store it. This means you don't /// have to copy the buffer to consume it. -template <typename T, typename RefCount = NonThreadSafeRefCount> +template <typename T, typename ThreadTraits = ThreadSafeThreadTraits> class CompletionCallbackFactory { public: @@ -200,26 +200,35 @@ class CompletionCallbackFactory { /// parameter is <code>NULL</code>. explicit CompletionCallbackFactory(T* object = NULL) : object_(object) { + // Assume that we don't need to lock since construction should be complete + // before the pointer is used on another thread. InitBackPointer(); } /// Destructor. ~CompletionCallbackFactory() { + // Assume that we don't need to lock since this object should not be used + // from multiple threads during destruction. ResetBackPointer(); } /// CancelAll() cancels all <code>CompletionCallbacks</code> allocated from /// this factory. void CancelAll() { + typename ThreadTraits::AutoLock lock(lock_); + ResetBackPointer(); InitBackPointer(); } + /// Initialize() binds the <code>CallbackFactory</code> to a particular /// object. Use this when the object is not available at /// <code>CallbackFactory</code> creation, and the <code>NULL</code> default /// is passed to the constructor. The object may only be initialized once, /// either by the constructor, or by a call to Initialize(). /// + /// This class may not be used on any thread until initialization is complete. + /// /// @param[in] object The object whose member functions are to be bound to /// the <code>CompletionCallback</code> created by this /// <code>CompletionCallbackFactory</code>. @@ -247,7 +256,6 @@ class CompletionCallbackFactory { /// @return A <code>CompletionCallback</code>. template <typename Method> CompletionCallback NewCallback(Method method) { - PP_DCHECK(object_); return NewCallbackHelper(new Dispatcher0<Method>(method)); } @@ -302,7 +310,6 @@ class CompletionCallbackFactory { /// @return A <code>CompletionCallback</code>. template <typename Method, typename A> CompletionCallback NewCallback(Method method, const A& a) { - PP_DCHECK(object_); return NewCallbackHelper(new Dispatcher1<Method, A>(method, a)); } @@ -369,7 +376,6 @@ class CompletionCallbackFactory { /// @return A <code>CompletionCallback</code>. template <typename Method, typename A, typename B> CompletionCallback NewCallback(Method method, const A& a, const B& b) { - PP_DCHECK(object_); return NewCallbackHelper(new Dispatcher2<Method, A, B>(method, a, b)); } @@ -451,7 +457,6 @@ class CompletionCallbackFactory { template <typename Method, typename A, typename B, typename C> CompletionCallback NewCallback(Method method, const A& a, const B& b, const C& c) { - PP_DCHECK(object_); return NewCallbackHelper(new Dispatcher3<Method, A, B, C>(method, a, b, c)); } @@ -522,7 +527,7 @@ class CompletionCallbackFactory { private: class BackPointer { public: - typedef CompletionCallbackFactory<T, RefCount> FactoryType; + typedef CompletionCallbackFactory<T, ThreadTraits> FactoryType; explicit BackPointer(FactoryType* factory) : factory_(factory) { @@ -546,7 +551,7 @@ class CompletionCallbackFactory { } private: - RefCount ref_; + typename ThreadTraits::RefCount ref_; FactoryType* factory_; }; @@ -817,19 +822,26 @@ class CompletionCallbackFactory { typename Traits::StorageType output_; }; + // Creates the back pointer object and takes a reference to it. This assumes + // either that the lock is held or that it is not needed. void InitBackPointer() { back_pointer_ = new BackPointer(this); back_pointer_->AddRef(); } + // Releases our reference to the back pointer object and clears the pointer. + // This assumes either that the lock is held or that it is not needed. void ResetBackPointer() { back_pointer_->DropFactory(); back_pointer_->Release(); + back_pointer_ = NULL; } // Takes ownership of the dispatcher pointer, which should be heap allocated. template <typename Dispatcher> CompletionCallback NewCallbackHelper(Dispatcher* dispatcher) { + typename ThreadTraits::AutoLock lock(lock_); + PP_DCHECK(object_); // Expects a non-null object! return CompletionCallback( &CallbackData<Dispatcher>::Thunk, @@ -841,6 +853,8 @@ class CompletionCallbackFactory { typename internal::TypeUnwrapper< typename Dispatcher::OutputType>::StorageType> NewCallbackWithOutputHelper(Dispatcher* dispatcher) { + typename ThreadTraits::AutoLock lock(lock_); + PP_DCHECK(object_); // Expects a non-null object! CallbackData<Dispatcher>* data = new CallbackData<Dispatcher>(back_pointer_, dispatcher); @@ -855,7 +869,14 @@ class CompletionCallbackFactory { CompletionCallbackFactory(const CompletionCallbackFactory&); CompletionCallbackFactory& operator=(const CompletionCallbackFactory&); + // Never changed once initialized so does not need protection by the lock. T* object_; + + // Protects the back pointer. + typename ThreadTraits::Lock lock_; + + // Protected by the lock. This will get reset when you do CancelAll, for + // example. BackPointer* back_pointer_; }; diff --git a/ppapi/utility/completion_callback_factory_thread_traits.h b/ppapi/utility/completion_callback_factory_thread_traits.h new file mode 100644 index 0000000..2242b5c --- /dev/null +++ b/ppapi/utility/completion_callback_factory_thread_traits.h @@ -0,0 +1,178 @@ +// Copyright (c) 2012 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.
+
+#ifndef PPAPI_UTILITY_THREAD_SAFE_THREAD_TRAITS_H_
+#define PPAPI_UTILITY_THREAD_SAFE_THREAD_TRAITS_H_
+
+#include "ppapi/cpp/logging.h"
+#include "ppapi/cpp/module.h"
+#include "ppapi/utility/threading/lock.h"
+
+/// @file
+/// Defines the traits structures for thread-safety of a completion callback
+/// factory. We provide thread-safe and non-thread-safe version. The thread-safe
+/// version is always correct (if you follow the thread usage rules of the
+/// callback factory), but if you know your object will only be used on one
+/// thread, you can uses the non-thread-safe version.
+///
+/// The traits defines three nested classes to perform reference counting,
+/// locks, and scoped locking.
+
+namespace pp {
+
+/// The thread-safe version of thread traits. Using this class as the "traits"
+/// template argument to a completion callback factory will make it "somewhat
+/// thread-friendly." It will allow you to create completion callbacks from
+/// background threads and post them to another thread to run.
+///
+/// Care still must be taken to ensure that the completion callbacks are
+/// executed on the same thread that the factory is destroyed on to avoid a
+/// race on destruction.
+///
+/// Implementation note: this uses a lock instead of atomic add instructions.
+/// The number of platforms we need to support right now makes atomic
+/// operations unwieldy for this case that we don't actually use that often.
+/// As a further optimization, we can add support for this later.
+class ThreadSafeThreadTraits {
+ public:
+ class RefCount {
+ public:
+ /// Default constructor. In debug mode, this checks that the object is being
+ /// created on the main thread.
+ RefCount() : ref_(0) {
+ }
+
+ /// AddRef() increments the reference counter.
+ ///
+ /// @return An int32_t with the incremented reference counter.
+ int32_t AddRef() {
+ AutoLock lock(lock_);
+ return ++ref_;
+ }
+
+ /// Release() decrements the reference counter.
+ ///
+ /// @return An int32_t with the decremeneted reference counter.
+ int32_t Release() {
+ AutoLock lock(lock_);
+ PP_DCHECK(ref_ > 0);
+ return --ref_;
+ }
+
+ private:
+ Lock lock_;
+ int32_t ref_;
+ };
+
+ typedef pp::Lock Lock;
+ typedef pp::AutoLock AutoLock;
+};
+
+/// The non-thread-safe version of thread traits. Using this class as the
+/// "traits" template argument to a completion callback factory will make it
+/// not thread-safe but with potential extra performance.
+class NonThreadSafeThreadTraits {
+ public:
+ /// A simple reference counter that is not thread-safe.
+ ///
+ /// <strong>Note:</strong> in Debug mode, it checks that it is either called
+ /// on the main thread, or always called on another thread.
+ class RefCount {
+ public:
+ /// Default constructor. In debug mode, this checks that the object is being
+ /// created on the main thread.
+ RefCount() : ref_(0) {
+#ifndef NDEBUG
+ is_main_thread_ = Module::Get()->core()->IsMainThread();
+#endif
+ }
+
+ /// Destructor.
+ ~RefCount() {
+ PP_DCHECK(is_main_thread_ == Module::Get()->core()->IsMainThread());
+ }
+
+ /// AddRef() increments the reference counter.
+ ///
+ /// @return An int32_t with the incremented reference counter.
+ int32_t AddRef() {
+ PP_DCHECK(is_main_thread_ == Module::Get()->core()->IsMainThread());
+ return ++ref_;
+ }
+
+ /// Release() decrements the reference counter.
+ ///
+ /// @return An int32_t with the decremeneted reference counter.
+ int32_t Release() {
+ PP_DCHECK(is_main_thread_ == Module::Get()->core()->IsMainThread());
+ return --ref_;
+ }
+
+ private:
+ int32_t ref_;
+#ifndef NDEBUG
+ bool is_main_thread_;
+#endif
+ };
+
+ /// A simple object that acts like a lock but does nothing.
+ ///
+ /// MStrong>Note:</strong> in Debug mode, it checks that it is either
+ /// called on the main thread, or always called on another thread. It also
+ /// asserts that the caller does not recursively lock.
+ class Lock {
+ public:
+ Lock() {
+#ifndef NDEBUG
+ is_main_thread_ = Module::Get()->core()->IsMainThread();
+ lock_held_ = false;
+#endif
+ }
+
+ ~Lock() {
+ PP_DCHECK(is_main_thread_ == Module::Get()->core()->IsMainThread());
+ }
+
+ /// Acquires the fake "lock". This does nothing except perform checks in
+ /// debug mode.
+ void Acquire() {
+#ifndef NDEBUG
+ PP_DCHECK(!lock_held_);
+ lock_held_ = true;
+#endif
+ }
+
+ /// Releases the fake "lock". This does nothing except perform checks in
+ /// debug mode.
+ void Release() {
+#ifndef NDEBUG
+ PP_DCHECK(lock_held_);
+ lock_held_ = false;
+#endif
+ }
+
+ private:
+#ifndef NDEBUG
+ bool is_main_thread_;
+ bool lock_held_;
+#endif
+ };
+
+ class AutoLock {
+ public:
+ explicit AutoLock(Lock& lock) : lock_(lock) {
+ lock_.Acquire();
+ }
+ ~AutoLock() {
+ lock_.Release();
+ }
+
+ private:
+ Lock& lock_;
+ };
+};
+
+} // namespace pp
+
+#endif // PPAPI_UTILITY_THREAD_SAFE_THREAD_TRAITS_H_
diff --git a/ppapi/utility/non_thread_safe_ref_count.h b/ppapi/utility/non_thread_safe_ref_count.h index db00b7d..32943fe 100644 --- a/ppapi/utility/non_thread_safe_ref_count.h +++ b/ppapi/utility/non_thread_safe_ref_count.h @@ -1,60 +1 @@ -// Copyright (c) 2011 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. - -#ifndef PPAPI_UTILITY_NON_THREAD_SAFE_REF_COUNT_H_ -#define PPAPI_UTILITY_NON_THREAD_SAFE_REF_COUNT_H_ - -#include "ppapi/cpp/core.h" -#include "ppapi/cpp/logging.h" -#include "ppapi/cpp/module.h" - -/// @file -/// This file defines the APIs for maintaining a reference counter. -namespace pp { - -/// A simple reference counter that is not thread-safe. <strong>Note:</strong> -/// in Debug mode, it checks that it is either called on the main thread, or -/// always called on another thread. -class NonThreadSafeRefCount { - public: - /// Default constructor. In debug mode, this checks that the object is being - /// created on the main thread. - NonThreadSafeRefCount() - : ref_(0) { -#ifndef NDEBUG - is_main_thread_ = Module::Get()->core()->IsMainThread(); -#endif - } - - /// Destructor. - ~NonThreadSafeRefCount() { - PP_DCHECK(is_main_thread_ == Module::Get()->core()->IsMainThread()); - } - - /// AddRef() increments the reference counter. - /// - /// @return An int32_t with the incremented reference counter. - int32_t AddRef() { - PP_DCHECK(is_main_thread_ == Module::Get()->core()->IsMainThread()); - return ++ref_; - } - - /// Release() decrements the reference counter. - /// - /// @return An int32_t with the decremeneted reference counter. - int32_t Release() { - PP_DCHECK(is_main_thread_ == Module::Get()->core()->IsMainThread()); - return --ref_; - } - - private: - int32_t ref_; -#ifndef NDEBUG - bool is_main_thread_; -#endif -}; - -} // namespace pp - -#endif // PPAPI_UTILITY_NON_THREAD_SAFE_REF_COUNT_H_ +// This file should be erased diff --git a/ppapi/utility/threading/lock.cc b/ppapi/utility/threading/lock.cc new file mode 100644 index 0000000..12cbd08 --- /dev/null +++ b/ppapi/utility/threading/lock.cc @@ -0,0 +1,49 @@ +// Copyright (c) 2012 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 "ppapi/utility/threading/lock.h"
+
+namespace pp {
+
+#ifdef WIN32 // Windows implementation for native plugins.
+
+Lock::Lock() {
+ // The second parameter is the spin count; for short-held locks it avoids the
+ // contending thread from going to sleep which helps performance greatly.
+ ::InitializeCriticalSectionAndSpinCount(&os_lock_, 2000);
+}
+
+Lock::~Lock() {
+ ::DeleteCriticalSection(&os_lock_);
+}
+
+void Lock::Acquire() {
+ ::EnterCriticalSection(&os_lock_);
+}
+
+void Lock::Release() {
+ ::LeaveCriticalSection(&os_lock_);
+}
+
+#else // Posix implementation.
+
+Lock::Lock() {
+ pthread_mutex_init(&os_lock_, NULL);
+}
+
+Lock::~Lock() {
+ pthread_mutex_destroy(&os_lock_);
+}
+
+void Lock::Acquire() {
+ pthread_mutex_lock(&os_lock_);
+}
+
+void Lock::Release() {
+ pthread_mutex_unlock(&os_lock_);
+}
+
+#endif
+
+} // namespace pp
diff --git a/ppapi/utility/threading/lock.h b/ppapi/utility/threading/lock.h new file mode 100644 index 0000000..71a9876 --- /dev/null +++ b/ppapi/utility/threading/lock.h @@ -0,0 +1,84 @@ +// Copyright (c) 2012 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.
+
+#ifndef PPAPI_UTILITY_THREADING_LOCK_H_
+#define PPAPI_UTILITY_THREADING_LOCK_H_
+
+#ifdef WIN32
+#include <windows.h>
+#else
+#include <pthread.h>
+#endif
+
+namespace pp {
+
+/// A simple wrapper around a platform-specific lock. See also AutoLock.
+class Lock {
+ public:
+ /// Creates a lock in the "not held" state.
+ Lock();
+
+ /// Destroys the lock.
+ ~Lock();
+
+ /// Acquires the lock, blocking if it's already held by a different thread.
+ /// The lock must not already be held on the current thread (i.e. recursive
+ /// locks are not supported).
+ ///
+ /// Most callers should consider using an AutoLock instead to automatically
+ /// acquire and release the lock.
+ void Acquire();
+
+ /// Releases the lock. This must be paired with a call to Acquire().
+ void Release();
+
+ private:
+#if defined(WIN32)
+ typedef CRITICAL_SECTION OSLockType;
+#else
+ typedef pthread_mutex_t OSLockType;
+#endif
+
+ OSLockType os_lock_;
+
+ // Copy and assign not supported.
+ Lock(const Lock&);
+ Lock& operator=(const Lock&);
+};
+
+/// A helper class that scopes holding a lock.
+///
+/// @code
+/// class MyClass {
+/// public:
+/// void DoSomething() {
+/// pp::AutoLock lock(lock_);
+/// ...do something with the lock held...
+/// }
+///
+/// private:
+/// pp::Lock lock_;
+/// };
+/// @endcode
+class AutoLock {
+ public:
+ explicit AutoLock(Lock& lock) : lock_(lock) {
+ lock_.Acquire();
+ }
+
+ ~AutoLock() {
+ lock_.Release();
+ }
+
+ private:
+ Lock& lock_;
+
+ // Copy and assign not supported.
+ AutoLock(const AutoLock&);
+ AutoLock& operator=(const AutoLock&);
+};
+
+} // namespace pp
+
+#endif // PPAPI_UTILITY_THREADING_LOCK_H_
diff --git a/ppapi/utility/websocket/websocket_api.cc b/ppapi/utility/websocket/websocket_api.cc index db4e01a..c251539 100644 --- a/ppapi/utility/websocket/websocket_api.cc +++ b/ppapi/utility/websocket/websocket_api.cc @@ -13,6 +13,10 @@ #include "ppapi/cpp/websocket.h" #include "ppapi/utility/completion_callback_factory.h" +#ifdef SendMessage +#undef SendMessage +#endif + namespace pp { class WebSocketAPI::Implement : public WebSocket { |