dispatch_context_for_key.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /*
  2. * Copyright (c) 2010-2011 Apple Inc. All rights reserved.
  3. *
  4. * @APPLE_APACHE_LICENSE_HEADER_START@
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. *
  18. * @APPLE_APACHE_LICENSE_HEADER_END@
  19. */
  20. #include <dispatch/dispatch.h>
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
  24. #include <unistd.h>
  25. #endif
  26. #include <assert.h>
  27. #include <bsdtests.h>
  28. #include "dispatch_test.h"
  29. #if DISPATCH_API_VERSION >= 20100825 && DISPATCH_API_VERSION != 20101110
  30. static const char *ctxts[] = {"ctxt for app", "ctxt for key 1",
  31. "ctxt for key 2", "ctxt for key 1 bis", "ctxt for key 4"};
  32. volatile long ctxts_destroyed;
  33. static dispatch_group_t g;
  34. static void
  35. destructor(void *ctxt)
  36. {
  37. fprintf(stderr, "destructor of %s\n", (char*)ctxt);
  38. (void)__sync_add_and_fetch(&ctxts_destroyed, 1);
  39. dispatch_group_leave(g);
  40. }
  41. static void
  42. test_context_for_key(void)
  43. {
  44. g = dispatch_group_create();
  45. dispatch_queue_t q = dispatch_queue_create("q", NULL);
  46. #if DISPATCH_API_VERSION >= 20100518
  47. dispatch_queue_t tq = dispatch_queue_create("tq", DISPATCH_QUEUE_CONCURRENT);
  48. #else
  49. dispatch_queue_t tq = dispatch_queue_create("tq", NULL);
  50. dispatch_queue_set_width(tq, LONG_MAX);
  51. #endif
  52. dispatch_queue_t ttq = dispatch_get_global_queue(0, 0);
  53. dispatch_group_enter(g);
  54. #if DISPATCH_API_VERSION >= 20101011
  55. dispatch_queue_set_specific(tq, &ctxts[4], (char *)ctxts[4], destructor);
  56. #else
  57. dispatch_set_context_for_key(tq, &ctxts[4], ctxts[4], ttq, destructor);
  58. #endif
  59. dispatch_set_target_queue(tq, ttq);
  60. dispatch_group_enter(g);
  61. dispatch_set_context(q, (char *)ctxts[0]);
  62. dispatch_set_target_queue(q, tq);
  63. dispatch_set_finalizer_f(q, destructor);
  64. dispatch_async(q, ^{
  65. dispatch_group_enter(g);
  66. #if DISPATCH_API_VERSION >= 20101011
  67. dispatch_queue_set_specific(q, &ctxts[1], (char *)ctxts[1], destructor);
  68. #else
  69. dispatch_set_context_for_key(q, &ctxts[1], ctxts[1], ttq, destructor);
  70. #endif
  71. });
  72. dispatch_retain(q);
  73. dispatch_async(dispatch_get_global_queue(0, 0), ^{
  74. dispatch_group_enter(g);
  75. #if DISPATCH_API_VERSION >= 20101011
  76. dispatch_queue_set_specific(q, &ctxts[2], (char *)ctxts[2], destructor);
  77. #else
  78. dispatch_set_context_for_key(q, &ctxts[2], ctxts[2], ttq, destructor);
  79. #endif
  80. dispatch_async(dispatch_get_global_queue(0, 0), ^{
  81. void *ctxt;
  82. #if DISPATCH_API_VERSION >= 20101011
  83. ctxt = dispatch_queue_get_specific(q, &ctxts[2]);
  84. #else
  85. ctxt = dispatch_get_context_for_key(q, &ctxts[2]);
  86. #endif
  87. test_ptr("get context for key 2", ctxt, ctxts[2]);
  88. dispatch_release(q);
  89. });
  90. });
  91. dispatch_async(q, ^{
  92. void *ctxt;
  93. #if DISPATCH_API_VERSION >= 20101011
  94. ctxt = dispatch_get_specific(&ctxts[1]);
  95. test_ptr("get current context for key 1", ctxt, ctxts[1]);
  96. ctxt = dispatch_get_specific(&ctxts[4]);
  97. test_ptr("get current context for key 4 (on target queue)", ctxt, ctxts[4]);
  98. ctxt = dispatch_queue_get_specific(q, &ctxts[1]);
  99. #else
  100. ctxt = dispatch_get_context_for_key(tq, &ctxts[4]);
  101. test_ptr("get context for key 4 (on target queue)", ctxt, ctxts[4]);
  102. ctxt = dispatch_get_context_for_key(q, &ctxts[1]);
  103. #endif
  104. test_ptr("get context for key 1", ctxt, ctxts[1]);
  105. });
  106. dispatch_async(q, ^{
  107. dispatch_group_enter(g);
  108. void *ctxt;
  109. #if DISPATCH_API_VERSION >= 20101011
  110. dispatch_queue_set_specific(q, &ctxts[1], (char *)ctxts[3], destructor);
  111. ctxt = dispatch_queue_get_specific(q, &ctxts[1]);
  112. #else
  113. dispatch_set_context_for_key(q, &ctxts[1], ctxts[3], ttq, destructor);
  114. ctxt = dispatch_get_context_for_key(q, &ctxts[1]);
  115. #endif
  116. test_ptr("get context for key 1", ctxt, ctxts[3]);
  117. });
  118. dispatch_async(q, ^{
  119. void *ctxt;
  120. #if DISPATCH_API_VERSION >= 20101011
  121. dispatch_queue_set_specific(q, &ctxts[1], NULL, destructor);
  122. ctxt = dispatch_queue_get_specific(q, &ctxts[1]);
  123. #else
  124. dispatch_set_context_for_key(q, &ctxts[1], NULL, ttq, destructor);
  125. ctxt = dispatch_get_context_for_key(q, &ctxts[1]);
  126. #endif
  127. test_ptr("get context for key 1", ctxt, NULL);
  128. });
  129. void *ctxt = dispatch_get_context(q);
  130. test_ptr("get context for app", ctxt, ctxts[0]);
  131. dispatch_release(tq);
  132. dispatch_release(q);
  133. dispatch_group_wait(g, DISPATCH_TIME_FOREVER);
  134. test_long("contexts destroyed", ctxts_destroyed, 5);
  135. dispatch_release(g);
  136. }
  137. #endif
  138. int
  139. main(void)
  140. {
  141. dispatch_test_start("Dispatch Queue Specific"); // rdar://problem/8429188
  142. dispatch_async(dispatch_get_main_queue(), ^{
  143. #if DISPATCH_API_VERSION >= 20100825 && DISPATCH_API_VERSION != 20101110
  144. test_context_for_key();
  145. #endif
  146. test_stop();
  147. });
  148. dispatch_main();
  149. }