# class ThreadGroup

`ThreadGroup` provides a means of keeping track of a number of threads as a group.

A given `Thread` object can only belong to one `ThreadGroup` at a time; adding a thread to a new group will remove it from any previous group.

Newly created threads belong to the same group as the thread from which they were created.

### Constants

Default

  The default `ThreadGroup` created when Ruby starts; all Threads belong to it by default.

### Public Instance Methods

add(thread) → thgrp click to toggle source

Adds the given `thread` to this group, removing it from any other group to which it may have previously been a member.

    puts "Initial group is #{ThreadGroup::Default.list}"
    tg = ThreadGroup.new
    t1 = Thread.new { sleep }
    t2 = Thread.new { sleep }
    puts "t1 is #{t1}"
    puts "t2 is #{t2}"
    tg.add(t1)
    puts "Initial group now #{ThreadGroup::Default.list}"
    puts "tg group now #{tg.list}"

This will produce:

    Initial group is #<Thread:0x401bdf4c>
    t1 is #<Thread:0x401b3c90>
    t2 is #<Thread:0x401b3c18>
    Initial group now #<Thread:0x401b3c18>#<Thread:0x401bdf4c>
    tg group now #<Thread:0x401b3c90>

    static VALUE
    thgroup_add(VALUE group, VALUE thread)
    {
        rb_thread_t *target_th = rb_thread_ptr(thread);
        struct thgroup *data;

        if (OBJ_FROZEN(group)) {
            rb_raise(rb_eThreadError, "can't move to the frozen thread group");
        }
        TypedData_Get_Struct(group, struct thgroup, &thgroup_data_type, data);
        if (data->enclosed) {
            rb_raise(rb_eThreadError, "can't move to the enclosed thread group");
        }

        if (!target_th->thgroup) {
            return Qnil;
        }

        if (OBJ_FROZEN(target_th->thgroup)) {
            rb_raise(rb_eThreadError, "can't move from the frozen thread group");
        }
        TypedData_Get_Struct(target_th->thgroup, struct thgroup, &thgroup_data_type, data);
        if (data->enclosed) {
            rb_raise(rb_eThreadError,
                     "can't move from the enclosed thread group");
        }

        target_th->thgroup = group;
        return group;
    }

enclose → thgrp click to toggle source

Prevents threads from being added to or removed from the receiving `ThreadGroup`.

New threads can still be started in an enclosed `ThreadGroup`.

    ThreadGroup::Default.enclose        #=> #<ThreadGroup:0x4029d914>
    thr = Thread.new { Thread.stop }    #=> #<Thread:0x402a7210 sleep>
    tg = ThreadGroup.new                #=> #<ThreadGroup:0x402752d4>
    tg.add thr
    #=> ThreadError: can't move from the enclosed thread group

    static VALUE
    thgroup_enclose(VALUE group)
    {
        struct thgroup *data;

        TypedData_Get_Struct(group, struct thgroup, &thgroup_data_type, data);
        data->enclosed = 1;

        return group;
    }

enclosed? → true or false click to toggle source

Returns `true` if the `thgrp` is enclosed. See also `ThreadGroup#enclose`.

    static VALUE
    thgroup_enclosed_p(VALUE group)
    {
        struct thgroup *data;

        TypedData_Get_Struct(group, struct thgroup, &thgroup_data_type, data);
        if (data->enclosed)
            return Qtrue;
        return Qfalse;
    }

list → array click to toggle source

Returns an array of all existing `Thread` objects that belong to this group.

    ThreadGroup::Default.list   #=> [#<Thread:0x401bdf4c run>]

    static VALUE
    thgroup_list(VALUE group)
    {
        VALUE ary = rb_ary_new();
        rb_vm_t *vm = GET_THREAD()->vm;
        rb_thread_t *th = 0;

        list_for_each(&vm->living_threads, th, vmlt_node) {
            if (th->thgroup == group) {
                rb_ary_push(ary, th->self);
            }
        }
        return ary;
    }