tb_bool_t tb_transfer_pool_done(tb_transfer_pool_ref_t pool, tb_char_t const* iurl, tb_char_t const* ourl, tb_hize_t offset, tb_size_t rate, tb_async_transfer_done_func_t done, tb_async_transfer_ctrl_func_t ctrl, tb_cpointer_t priv) { // check tb_transfer_pool_impl_t* impl = (tb_transfer_pool_impl_t*)pool; tb_assert_and_check_return_val(impl && impl->aicp && iurl && ourl, tb_false); // enter tb_spinlock_enter(&impl->lock); // done tb_bool_t ok = tb_false; tb_transfer_task_t* task = tb_null; do { // check tb_check_break(TB_STATE_OK == tb_atomic_get(&impl->state)); // too many tasks? if (tb_list_entry_size(&impl->work) >= impl->maxn) { // trace tb_trace_e("too many tasks, done task: %s => %s failed!", iurl, ourl); break; } // init task task = tb_transfer_task_init(impl, done, ctrl, priv); tb_assert_and_check_break(task && task->transfer); // init transfer stream if (!tb_async_transfer_init_istream_from_url(task->transfer, iurl)) break; if (!tb_async_transfer_init_ostream_from_url(task->transfer, ourl)) break; // init transfer rate tb_async_transfer_limitrate(task->transfer, rate); // check tb_assert_and_check_break(impl->pool); // append to the work list tb_list_entry_insert_tail(&impl->work, &task->entry); // ok ok = tb_true; } while (0); // trace tb_trace_d("done: task: %p, %s => %s, work: %lu, idle: %lu, state: %s", task, iurl, ourl, tb_list_entry_size(&impl->work), tb_list_entry_size(&impl->idle), ok? "ok" : "no"); // failed? if (!ok) { // exit it if (task) tb_transfer_task_exit(impl, task); task = tb_null; } // leave tb_spinlock_leave(&impl->lock); // ok? done it if (ok && task && task->transfer) { // done if (!tb_async_transfer_open_done(task->transfer, 0, tb_transfer_task_done, task)) { // enter tb_spinlock_enter(&impl->lock); // remove task from the work list tb_list_entry_remove(&impl->work, &task->entry); // exit task tb_transfer_task_exit(impl, task); // leave tb_spinlock_leave(&impl->lock); // failed ok = tb_false; } } // ok? return ok; }
/* ////////////////////////////////////////////////////////////////////////////////////// * main */ tb_int_t tb_demo_stream_async_transfer_main(tb_int_t argc, tb_char_t** argv) { // done tb_async_transfer_ref_t transfer = tb_null; do { // init transfer transfer = tb_async_transfer_init(tb_null, tb_true); tb_assert_and_check_break(transfer); // init transfer stream if (!tb_async_transfer_init_istream_from_url(transfer, argv[1])) break; if (!tb_async_transfer_init_ostream_from_url(transfer, argv[2])) break; // limit rate tb_async_transfer_limitrate(transfer, argv[3]? tb_atoi(argv[3]) : 0); // trace tb_trace_i("done: .."); // open and done transfer if (!tb_async_transfer_open_done(transfer, 0, tb_demo_transfer_done_func, tb_null)) break; // wait getchar(); // trace tb_trace_i("pause: .."); // pause transfer tb_async_transfer_pause(transfer); // wait getchar(); // trace tb_trace_i("resume: .."); // resume transfer if (!tb_async_transfer_resume(transfer)) break; // wait getchar(); // trace tb_trace_i("done: .."); // open and done transfer if (!tb_async_transfer_open_done(transfer, 0, tb_demo_transfer_done_func, tb_null)) break; // wait getchar(); } while (0); // trace tb_trace_i("exit: .."); // exit transfer if (transfer) tb_async_transfer_exit(transfer); transfer = tb_null; return 0; }