|
38 | 38 |
|
39 | 39 | #include <stdint.h>
|
40 | 40 | #include <vector>
|
| 41 | +#include <unordered_map> |
41 | 42 |
|
42 | 43 | // Caveat emptor: we're going slightly crazy with macros here but the end
|
43 | 44 | // hopefully justifies the means. We have a lot of per-context properties
|
@@ -82,7 +83,6 @@ namespace node {
|
82 | 83 | V(address_string, "address") \
|
83 | 84 | V(args_string, "args") \
|
84 | 85 | V(async, "async") \
|
85 |
| - V(async_queue_string, "_asyncQueue") \ |
86 | 86 | V(buffer_string, "buffer") \
|
87 | 87 | V(bytes_string, "bytes") \
|
88 | 88 | V(bytes_parsed_string, "bytesParsed") \
|
@@ -282,6 +282,11 @@ struct node_ares_task {
|
282 | 282 | RB_ENTRY(node_ares_task) node;
|
283 | 283 | };
|
284 | 284 |
|
| 285 | +struct node_fd_async_ids { |
| 286 | + double async_id; |
| 287 | + double trigger_id; |
| 288 | +}; |
| 289 | + |
285 | 290 | RB_HEAD(node_ares_task_list, node_ares_task);
|
286 | 291 |
|
287 | 292 | class IsolateData {
|
@@ -322,22 +327,90 @@ class Environment {
|
322 | 327 | public:
|
323 | 328 | class AsyncHooks {
|
324 | 329 | public:
|
| 330 | + // Reason for both UidFields and Fields are that one is stored as a double* |
| 331 | + // and the other as a uint32_t*. |
| 332 | + enum UidFields { |
| 333 | + kAsyncUidCntr, |
| 334 | + kCurrentId, |
| 335 | + kTriggerId, |
| 336 | + kInitTriggerId, |
| 337 | + kScopedTriggerId, |
| 338 | + kUidFieldsCount, |
| 339 | + }; |
| 340 | + |
| 341 | + enum Fields { |
| 342 | + kInit, |
| 343 | + kBefore, |
| 344 | + kAfter, |
| 345 | + kDestroy, |
| 346 | + kActiveHooks, |
| 347 | + kFieldsCount, |
| 348 | + }; |
| 349 | + |
325 | 350 | inline uint32_t* fields();
|
326 | 351 | inline int fields_count() const;
|
327 |
| - inline bool callbacks_enabled(); |
328 |
| - inline void set_enable_callbacks(uint32_t flag); |
| 352 | + inline double* uid_fields(); |
| 353 | + inline int uid_fields_count() const; |
| 354 | + |
| 355 | + class InitScope { |
| 356 | + public: |
| 357 | + explicit InitScope(Environment* env, double init_trigger_id) |
| 358 | + : uid_fields_(env->async_hooks()->uid_fields()), |
| 359 | + init_trigger_id_(uid_fields_[AsyncHooks::kScopedTriggerId]) { |
| 360 | + uid_fields_[AsyncHooks::kScopedTriggerId] = init_trigger_id; |
| 361 | + } |
| 362 | + ~InitScope() { |
| 363 | + uid_fields_[AsyncHooks::kScopedTriggerId] = init_trigger_id_; |
| 364 | + } |
| 365 | + private: |
| 366 | + double* uid_fields_; |
| 367 | + const double init_trigger_id_; |
| 368 | + |
| 369 | + DISALLOW_COPY_AND_ASSIGN(InitScope); |
| 370 | + }; |
| 371 | + |
| 372 | + // ExecScope is meant for use in MakeCallback, to maintained stacked |
| 373 | + // state. |
| 374 | + // TODO(trevnorris): This conflicts with how emitBefore/emitAfter work |
| 375 | + // (manually tracking the stacks in a JS array). Technically they should |
| 376 | + // play nicely together, but write tests to prove this. |
| 377 | + class ExecScope { |
| 378 | + public: |
| 379 | + explicit ExecScope(Environment* env, double id, double trigger_id) |
| 380 | + : uid_fields_(env->async_hooks()->uid_fields()), |
| 381 | + id_(uid_fields_[AsyncHooks::kCurrentId]), |
| 382 | + trigger_id_(uid_fields_[AsyncHooks::kTriggerId]), |
| 383 | + disposed_(false) { |
| 384 | + uid_fields_[AsyncHooks::kCurrentId] = id; |
| 385 | + uid_fields_[AsyncHooks::kTriggerId] = trigger_id; |
| 386 | + } |
| 387 | + ~ExecScope() { |
| 388 | + if (disposed_) return; |
| 389 | + Dispose(); |
| 390 | + } |
| 391 | + void Dispose() { |
| 392 | + disposed_ = true; |
| 393 | + uid_fields_[AsyncHooks::kCurrentId] = id_; |
| 394 | + uid_fields_[AsyncHooks::kTriggerId] = trigger_id_; |
| 395 | + } |
| 396 | + |
| 397 | + private: |
| 398 | + double* uid_fields_; |
| 399 | + const double id_; |
| 400 | + const double trigger_id_; |
| 401 | + bool disposed_; |
| 402 | + |
| 403 | + DISALLOW_COPY_AND_ASSIGN(ExecScope); |
| 404 | + }; |
329 | 405 |
|
330 | 406 | private:
|
331 | 407 | friend class Environment; // So we can call the constructor.
|
332 | 408 | inline AsyncHooks();
|
333 | 409 |
|
334 |
| - enum Fields { |
335 |
| - // Set this to not zero if the init hook should be called. |
336 |
| - kEnableCallbacks, |
337 |
| - kFieldsCount |
338 |
| - }; |
339 |
| - |
340 | 410 | uint32_t fields_[kFieldsCount];
|
| 411 | + // Gives us 2^53-1 unique ids. Good enough for now and makes the operation |
| 412 | + // cheaper in JS. |
| 413 | + double uid_fields_[kUidFieldsCount]; |
341 | 414 |
|
342 | 415 | DISALLOW_COPY_AND_ASSIGN(AsyncHooks);
|
343 | 416 | };
|
@@ -442,7 +515,6 @@ class Environment {
|
442 | 515 |
|
443 | 516 | inline v8::Isolate* isolate() const;
|
444 | 517 | inline uv_loop_t* event_loop() const;
|
445 |
| - inline bool async_wrap_callbacks_enabled() const; |
446 | 518 | inline bool in_domain() const;
|
447 | 519 | inline uint32_t watched_providers() const;
|
448 | 520 |
|
@@ -479,7 +551,19 @@ class Environment {
|
479 | 551 | void PrintSyncTrace() const;
|
480 | 552 | inline void set_trace_sync_io(bool value);
|
481 | 553 |
|
482 |
| - inline double get_async_wrap_uid(); |
| 554 | + // The necessary API for async_hooks. |
| 555 | + inline double new_async_uid(); |
| 556 | + inline double current_async_id(); |
| 557 | + inline double exchange_current_async_id(const double id); |
| 558 | + inline double trigger_id(); |
| 559 | + inline double exchange_trigger_id(const double id); |
| 560 | + inline double exchange_init_trigger_id(const double id); |
| 561 | + inline void set_init_trigger_id(const double id); |
| 562 | + |
| 563 | + // For propagating hook id's with a file descriptor. |
| 564 | + inline void erase_fd_async_id(int fd); |
| 565 | + inline node_fd_async_ids get_fd_async_id(int fd); |
| 566 | + inline void insert_fd_async_ids(int fd, double async_id, double trigger_id); |
483 | 567 |
|
484 | 568 | // List of id's that have been destroyed and need the destroy() cb called.
|
485 | 569 | inline std::vector<double>* destroy_ids_list();
|
@@ -583,6 +667,7 @@ class Environment {
|
583 | 667 | size_t makecallback_cntr_;
|
584 | 668 | double async_wrap_id_;
|
585 | 669 | std::vector<double> destroy_ids_list_;
|
| 670 | + std::unordered_map<int, node_fd_async_ids> fd_async_id_map_; |
586 | 671 | debugger::Agent debugger_agent_;
|
587 | 672 | #if HAVE_INSPECTOR
|
588 | 673 | inspector::Agent inspector_agent_;
|
|
0 commit comments