 Chromium Code Reviews
 Chromium Code Reviews Issue 4118004:
  Update NetLog to be thread safe.  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src/
    
  
    Issue 4118004:
  Update NetLog to be thread safe.  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src/| Index: chrome/browser/net/chrome_net_log.h | 
| =================================================================== | 
| --- chrome/browser/net/chrome_net_log.h (revision 65207) | 
| +++ chrome/browser/net/chrome_net_log.h (working copy) | 
| @@ -6,8 +6,10 @@ | 
| #define CHROME_BROWSER_NET_CHROME_NET_LOG_H_ | 
| #pragma once | 
| +#include "base/atomicops.h" | 
| #include "base/observer_list.h" | 
| #include "base/scoped_ptr.h" | 
| +#include "chrome/browser/browser_thread.h" | 
| #include "net/base/net_log.h" | 
| class LoadTimingObserver; | 
| @@ -17,6 +19,10 @@ | 
| // ChromeNetLog is an implementation of NetLog that dispatches network log | 
| // messages to a list of observers. | 
| // | 
| +// All methods are threadsafe, with the exception that no ChromeNetLog or | 
| +// ChromeNetLog::Observer functions may be called by an Observer's OnAddEntry() | 
| +// method. | 
| +// | 
| // By default, ChromeNetLog will attach the observer PassiveLogCollector which | 
| // will keep track of recent request information (which used when displaying | 
| // the about:net-internals page). | 
| @@ -25,6 +31,28 @@ | 
| // | 
| class ChromeNetLog : public net::NetLog { | 
| public: | 
| + // This structure encapsulates all of the parameters of an event, | 
| + // including an "order" field that identifies when it was captured relative | 
| + // to other events. | 
| + struct Entry { | 
| 
eroman
2010/11/17 05:59:02
I see, you moved this out of PassiveLogCollector b
 
mmenke
2010/11/17 21:42:14
Reason I didn't do that is because EntryList is an
 | 
| + Entry(uint32 order, | 
| + net::NetLog::EventType type, | 
| + const base::TimeTicks& time, | 
| + net::NetLog::Source source, | 
| + net::NetLog::EventPhase phase, | 
| + net::NetLog::EventParameters* params); | 
| + ~Entry(); | 
| + | 
| + uint32 order; | 
| + net::NetLog::EventType type; | 
| + base::TimeTicks time; | 
| + net::NetLog::Source source; | 
| + net::NetLog::EventPhase phase; | 
| + scoped_refptr<net::NetLog::EventParameters> params; | 
| + }; | 
| + | 
| + typedef std::vector<Entry> EntryList; | 
| + | 
| // Interface for observing the events logged by the network stack. | 
| class Observer { | 
| 
eroman
2010/11/17 05:59:02
I suggest renaming this to "ThreadSafeObserver".
 
mmenke
2010/11/17 21:42:14
Done.
 | 
| public: | 
| @@ -35,10 +63,16 @@ | 
| // | 
| // Observers that need to see the full granularity of events can | 
| // specify LOG_ALL. However doing so will have performance consequences, | 
| - // and may cause PassiveLogCollector to use more memory than anticiapted. | 
| + // and may cause PassiveLogCollector to use more memory than anticipated. | 
| 
eroman
2010/11/17 05:59:02
thanks for fixing the typo!
 | 
| + // | 
| + // Observers will be called on the same thread an entry is added on, | 
| + // and are responsible for ensuring their own thread safety. | 
| explicit Observer(LogLevel log_level); | 
| virtual ~Observer() {} | 
| + | 
| + // It is illegal for an Observer to call any ChromeNetLog or | 
| + // ChromeNetLog::Observer functions in response to a call to OnAddEntry. | 
| 
eroman
2010/11/17 05:59:02
I suggest additionaly re-iterating the threading m
 | 
| virtual void OnAddEntry(EventType type, | 
| const base::TimeTicks& time, | 
| const Source& source, | 
| @@ -46,7 +80,9 @@ | 
| EventParameters* params) = 0; | 
| LogLevel log_level() const; | 
| protected: | 
| - void set_log_level(LogLevel log_level); | 
| + // |net_log| is the ChromeNetLog the Observer is currently observing, | 
| + // and cannot be NULL. | 
| + void SetLogLevel(LogLevel log_level, ChromeNetLog* net_log); | 
| 
eroman
2010/11/17 05:59:02
Taking the ChromeNetLog* here isn't very intuitive
 
mmenke
2010/11/17 21:42:14
Done.  Only thing I don't like about that is that
 | 
| private: | 
| LogLevel log_level_; | 
| DISALLOW_COPY_AND_ASSIGN(Observer); | 
| @@ -67,6 +103,13 @@ | 
| void AddObserver(Observer* observer); | 
| void RemoveObserver(Observer* observer); | 
| + // Adds |observer| and writes all passively captured events to | 
| + // |passive_entries|. Guarantees that no events in |passive_entries| will be | 
| + // sent to |observer| and all future events that have yet been sent to the | 
| + // PassiveLogCollector will be sent to |observer|. | 
| + void AddObserverAndGetAllCapturedEvents(Observer* observer, | 
| 
eroman
2010/11/17 05:59:02
I have a reputation for writing incredibly long fu
 
mmenke
2010/11/17 21:42:14
I'm fine with it, actually.  Only thing I have aga
 | 
| + EntryList* passive_entries); | 
| + | 
| PassiveLogCollector* passive_collector() { | 
| return passive_collector_.get(); | 
| } | 
| @@ -76,14 +119,20 @@ | 
| } | 
| private: | 
| - uint32 next_id_; | 
| + // Called whenever an Observer is added or removed, or changes its log level. | 
| + // Must have acquired |lock_| prior to calling. | 
| + void UpdateLogLevel_(); | 
| + | 
| + Lock lock_; | 
| + | 
| + base::subtle::Atomic32 last_id_; | 
| + base::subtle::Atomic32 log_level_; | 
| + | 
| scoped_ptr<PassiveLogCollector> passive_collector_; | 
| scoped_ptr<LoadTimingObserver> load_timing_observer_; | 
| scoped_ptr<NetLogLogger> net_log_logger_; | 
| - // Note that this needs to be "mutable" so we can iterate over the observer | 
| - // list in GetLogLevel(). | 
| - mutable ObserverList<Observer, true> observers_; | 
| + ObserverList<Observer, true> observers_; | 
| 
eroman
2010/11/17 05:59:02
Can you mention that |lock_| must be held whenever
 | 
| DISALLOW_COPY_AND_ASSIGN(ChromeNetLog); | 
| }; |