From 9ab7a7fb13136fe95b59e7a81a2343019de7919d Mon Sep 17 00:00:00 2001
From: Dario Casalinuovo <b.vitruvio@gmail.com>
Date: Tue, 17 Mar 2015 21:03:17 +0100
Subject: [PATCH 3/3] TimeSource: Rework SlaveNodes management using TMap.
---
src/kits/media/TimeSource.cpp | 186 +++++++++++++++++++++++++-----------------
1 file changed, 112 insertions(+), 74 deletions(-)
diff --git a/src/kits/media/TimeSource.cpp b/src/kits/media/TimeSource.cpp
index 3ceee37..f3f6ad2 100644
a
|
b
|
|
2 | 2 | * Copyright 2002-2012, Haiku. All Rights Reserved. |
3 | 3 | * This file may be used under the terms of the MIT License. |
4 | 4 | * |
5 | | * Author: Marcus Overhagen |
| 5 | * Authors: |
| 6 | * Dario Casalinuovo |
| 7 | * Marcus Overhagen |
6 | 8 | */ |
7 | 9 | |
8 | 10 | |
… |
… |
|
16 | 18 | #include "DataExchange.h" |
17 | 19 | #include "ServerInterface.h" |
18 | 20 | #include "TimeSourceObject.h" |
| 21 | #include "TMap.h" |
19 | 22 | |
20 | 23 | #define DEBUG_TIMESOURCE 0 |
21 | 24 | |
… |
… |
struct TimeSourceTransmit
|
45 | 48 | float drift[TS_INDEX_COUNT]; |
46 | 49 | }; |
47 | 50 | |
48 | | #define SLAVE_NODES_COUNT 300 |
| 51 | #define MAX_SLAVE_NODES 300 |
49 | 52 | |
50 | | // XXX TODO: storage for slave nodes uses public data members, this should be changed |
51 | 53 | |
52 | | class SlaveNodes |
| 54 | class SlaveNodes : public BLocker |
53 | 55 | { |
54 | 56 | public: |
55 | | SlaveNodes(); |
56 | | ~SlaveNodes(); |
57 | | public: |
58 | | BLocker * locker; |
59 | | int32 count; |
60 | | media_node_id node_id[SLAVE_NODES_COUNT]; |
61 | | port_id node_port[SLAVE_NODES_COUNT]; |
| 57 | SlaveNodes(); |
| 58 | ~SlaveNodes(); |
| 59 | |
| 60 | int32 CountSlaves() const; |
| 61 | bool GetNextSlave(port_id** id); |
| 62 | void Rewind(); |
| 63 | |
| 64 | bool InsertSlave(const media_node& node); |
| 65 | bool RemoveSlave(const media_node& node); |
| 66 | private: |
| 67 | Map<media_node_id, port_id> fSlaveList; |
62 | 68 | }; |
63 | 69 | |
64 | 70 | |
65 | 71 | SlaveNodes::SlaveNodes() |
| 72 | : |
| 73 | BLocker("BTimeSource slavenodes") |
66 | 74 | { |
67 | | locker = new BLocker("BTimeSource SlaveNodes"); |
68 | | count = 0; |
69 | | memset(node_id, 0, sizeof(node_id)); |
70 | | memset(node_port, 0, sizeof(node_port)); |
71 | 75 | } |
72 | 76 | |
73 | 77 | |
74 | 78 | SlaveNodes::~SlaveNodes() |
75 | 79 | { |
76 | | delete locker; |
| 80 | fSlaveList.MakeEmpty(); |
| 81 | } |
| 82 | |
| 83 | |
| 84 | int32 |
| 85 | SlaveNodes::CountSlaves() const |
| 86 | { |
| 87 | return fSlaveList.CountItems(); |
| 88 | } |
| 89 | |
| 90 | |
| 91 | bool |
| 92 | SlaveNodes::GetNextSlave(port_id** id) |
| 93 | { |
| 94 | return fSlaveList.GetNext(id); |
77 | 95 | } |
78 | 96 | |
79 | 97 | |
80 | | } } |
| 98 | void |
| 99 | SlaveNodes::Rewind() |
| 100 | { |
| 101 | fSlaveList.Rewind(); |
| 102 | } |
| 103 | |
| 104 | |
| 105 | bool |
| 106 | SlaveNodes::InsertSlave(const media_node& node) |
| 107 | { |
| 108 | return fSlaveList.Insert(node.node, node.port); |
| 109 | } |
| 110 | |
| 111 | |
| 112 | bool |
| 113 | SlaveNodes::RemoveSlave(const media_node& node) |
| 114 | { |
| 115 | return fSlaveList.Remove(node.node); |
| 116 | } |
| 117 | |
| 118 | |
| 119 | } } // namespace BPrivate::media |
81 | 120 | |
82 | 121 | |
83 | 122 | /************************************************************* |
… |
… |
BTimeSource::BroadcastTimeWarp(bigtime_t at_real_time,
|
343 | 382 | ", new_performance_time %" B_PRId64 "\n", at_real_time, |
344 | 383 | new_performance_time); |
345 | 384 | |
346 | | BAutolock lock(fSlaveNodes->locker); |
| 385 | BAutolock lock(fSlaveNodes); |
347 | 386 | |
348 | | for (int i = 0, n = 0; i < SLAVE_NODES_COUNT && n != fSlaveNodes->count; i++) { |
349 | | if (fSlaveNodes->node_id[i] != 0) { |
350 | | node_time_warp_command cmd; |
351 | | cmd.at_real_time = at_real_time; |
352 | | cmd.to_performance_time = new_performance_time; |
353 | | SendToPort(fSlaveNodes->node_port[i], NODE_TIME_WARP, &cmd, sizeof(cmd)); |
354 | | n++; |
355 | | } |
| 387 | port_id* port = NULL; |
| 388 | while (fSlaveNodes->GetNextSlave(&port) == true) { |
| 389 | node_time_warp_command cmd; |
| 390 | cmd.at_real_time = at_real_time; |
| 391 | cmd.to_performance_time = new_performance_time; |
| 392 | SendToPort(*port, NODE_TIME_WARP, |
| 393 | &cmd, sizeof(cmd)); |
356 | 394 | } |
| 395 | fSlaveNodes->Rewind(); |
357 | 396 | } |
358 | 397 | |
359 | 398 | |
… |
… |
BTimeSource::SendRunMode(run_mode mode)
|
365 | 404 | |
366 | 405 | // send the run mode change to all slaved nodes |
367 | 406 | |
368 | | BAutolock lock(fSlaveNodes->locker); |
| 407 | BAutolock lock(fSlaveNodes); |
369 | 408 | |
370 | | for (int i = 0, n = 0; i < SLAVE_NODES_COUNT && n != fSlaveNodes->count; i++) { |
371 | | if (fSlaveNodes->node_id[i] != 0) { |
372 | | node_set_run_mode_command cmd; |
373 | | cmd.mode = mode; |
374 | | SendToPort(fSlaveNodes->node_port[i], NODE_SET_RUN_MODE, &cmd, sizeof(cmd)); |
375 | | n++; |
376 | | } |
| 409 | port_id* port = NULL; |
| 410 | while (fSlaveNodes->GetNextSlave(&port) == true) { |
| 411 | node_set_run_mode_command cmd; |
| 412 | cmd.mode = mode; |
| 413 | SendToPort(*port, NODE_SET_RUN_MODE, |
| 414 | &cmd, sizeof(cmd)); |
377 | 415 | } |
| 416 | fSlaveNodes->Rewind(); |
378 | 417 | } |
379 | 418 | |
380 | 419 | |
… |
… |
BTimeSource::BTimeSource(media_node_id id)
|
420 | 459 | // BPrivate::media::TimeSourceObject objects |
421 | 460 | // We create a clone of the communication area. |
422 | 461 | char name[32]; |
423 | | area_id area; |
424 | 462 | sprintf(name, "__timesource_buf_%" B_PRId32, id); |
425 | | area = find_area(name); |
| 463 | area_id area = find_area(name); |
426 | 464 | if (area <= 0) { |
427 | 465 | ERROR("BTimeSource::BTimeSource couldn't find area, node %" B_PRId32 |
428 | 466 | "\n", id); |
… |
… |
BTimeSource::DirectAddMe(const media_node& node)
|
512 | 550 | |
513 | 551 | CALLED(); |
514 | 552 | ASSERT(fSlaveNodes != NULL); |
515 | | BAutolock lock(fSlaveNodes->locker); |
| 553 | BAutolock lock(fSlaveNodes); |
516 | 554 | |
517 | | if (fSlaveNodes->count == SLAVE_NODES_COUNT) { |
518 | | ERROR("BTimeSource::DirectAddMe out of slave node slots\n"); |
| 555 | if (fSlaveNodes->CountSlaves() == MAX_SLAVE_NODES) { |
| 556 | ERROR("BTimeSource::DirectAddMe reached maximum number of slaves\n"); |
519 | 557 | return; |
520 | 558 | } |
521 | 559 | if (fNodeID == node.node) { |
522 | 560 | ERROR("BTimeSource::DirectAddMe should not add itself to slave nodes\n"); |
523 | 561 | return; |
524 | 562 | } |
525 | | for (int i = 0; i < SLAVE_NODES_COUNT; i++) { |
526 | | if (fSlaveNodes->node_id[i] == 0) { |
527 | | fSlaveNodes->node_id[i] = node.node; |
528 | | fSlaveNodes->node_port[i] = node.port; |
529 | | fSlaveNodes->count += 1; |
530 | | if (fSlaveNodes->count == 1) { |
531 | | // start the time source |
532 | | time_source_op_info msg; |
533 | | msg.op = B_TIMESOURCE_START; |
534 | | msg.real_time = RealTime(); |
535 | | TRACE_TIMESOURCE("starting time source %" B_PRId32 "\n", ID()); |
536 | | write_port(fControlPort, TIMESOURCE_OP, &msg, sizeof(msg)); |
537 | | } |
538 | | return; |
539 | | } |
| 563 | |
| 564 | if (fSlaveNodes->InsertSlave(node) != true) { |
| 565 | ERROR("BTimeSource::DirectAddMe failed\n"); |
| 566 | return; |
540 | 567 | } |
541 | | ERROR("BTimeSource::DirectAddMe failed\n"); |
542 | | } |
| 568 | |
| 569 | if (fSlaveNodes->CountSlaves() == 1) { |
| 570 | // start the time source |
| 571 | time_source_op_info msg; |
| 572 | msg.op = B_TIMESOURCE_START; |
| 573 | msg.real_time = RealTime(); |
| 574 | |
| 575 | TRACE_TIMESOURCE("starting time source %" B_PRId32 "\n", ID()); |
| 576 | |
| 577 | write_port(fControlPort, TIMESOURCE_OP, &msg, sizeof(msg)); |
| 578 | } |
| 579 | } |
| 580 | |
543 | 581 | |
544 | 582 | void |
545 | 583 | BTimeSource::DirectRemoveMe(const media_node& node) |
… |
… |
BTimeSource::DirectRemoveMe(const media_node& node)
|
549 | 587 | |
550 | 588 | CALLED(); |
551 | 589 | ASSERT(fSlaveNodes != NULL); |
552 | | BAutolock lock(fSlaveNodes->locker); |
| 590 | BAutolock lock(fSlaveNodes); |
553 | 591 | |
554 | | if (fSlaveNodes->count == 0) { |
| 592 | if (fSlaveNodes->CountSlaves() == 0) { |
555 | 593 | ERROR("BTimeSource::DirectRemoveMe no slots used\n"); |
556 | 594 | return; |
557 | 595 | } |
558 | | for (int i = 0; i < SLAVE_NODES_COUNT; i++) { |
559 | | if (fSlaveNodes->node_id[i] == node.node && fSlaveNodes->node_port[i] == node.port) { |
560 | | fSlaveNodes->node_id[i] = 0; |
561 | | fSlaveNodes->node_port[i] = 0; |
562 | | fSlaveNodes->count -= 1; |
563 | | if (fSlaveNodes->count == 0) { |
564 | | // stop the time source |
565 | | time_source_op_info msg; |
566 | | msg.op = B_TIMESOURCE_STOP_IMMEDIATELY; |
567 | | msg.real_time = RealTime(); |
568 | | TRACE_TIMESOURCE("stopping time source %" B_PRId32 "\n", ID()); |
569 | | write_port(fControlPort, TIMESOURCE_OP, &msg, sizeof(msg)); |
570 | | } |
571 | | return; |
572 | | } |
| 596 | |
| 597 | if (fSlaveNodes->RemoveSlave(node) != true) { |
| 598 | ERROR("BTimeSource::DirectRemoveMe failed\n"); |
| 599 | return; |
| 600 | } |
| 601 | |
| 602 | if (fSlaveNodes->CountSlaves() == 0) { |
| 603 | // stop the time source |
| 604 | time_source_op_info msg; |
| 605 | msg.op = B_TIMESOURCE_STOP_IMMEDIATELY; |
| 606 | msg.real_time = RealTime(); |
| 607 | |
| 608 | TRACE_TIMESOURCE("stopping time source %" B_PRId32 "\n", ID()); |
| 609 | |
| 610 | write_port(fControlPort, TIMESOURCE_OP, &msg, sizeof(msg)); |
573 | 611 | } |
574 | | ERROR("BTimeSource::DirectRemoveMe failed\n"); |
575 | 612 | } |
576 | 613 | |
| 614 | |
577 | 615 | void |
578 | 616 | BTimeSource::DirectStart(bigtime_t at) |
579 | 617 | { |