/* 总是将孩子节点加在子节点链的最右边 如果 obj 在对象树中 那么完成添加工作后一定要更新 root->parent 的 lchild 成员和 rchild 成员 这是为了保证遍历的正确 */ si_t object_insert_child(struct object* parent, struct object* child) { struct object* tree = NULL; if(NULL == parent) { return 0; } /* 父节点有右子节点 */ if(parent->rchild != NULL) { parent->rchild->parent = child; /* 父节点的右子节点作为自己的左子节点 */ child->lchild = parent->rchild; } child->parent = parent; parent->rchild = child; /* 找到这棵树根节点的父节点 */ tree = object_get_root(parent)->parent; /* child 在对象树中 */ /* 必须更新 root->parent 节点的 lchild 成员和 rchild 成员 */ /* 更新最左边节点 */ tree->lchild = object_tree_l_most_node(tree->parent); /* 更新最右边节点 */ tree->rchild = object_tree_r_most_node(tree->parent); return 0; }
void nmi_monitor_handle(int cpu_index, Error **errp) { struct do_nmi_s ns = { .cpu_index = cpu_index, .err = NULL, .handled = false }; nmi_children(object_get_root(), &ns); if (ns.handled) { error_propagate(errp, ns.err); } else { error_setg(errp, QERR_UNSUPPORTED); } } void inject_nmi(void) { #if defined(TARGET_I386) CPUState *cs; CPU_FOREACH(cs) { X86CPU *cpu = X86_CPU(cs); if (!cpu->apic_state) { cpu_interrupt(cs, CPU_INTERRUPT_NMI); } else { apic_deliver_nmi(cpu->apic_state); } } #else nmi_monitor_handle(0, NULL); #endif }
static void realize(DeviceState *d, Error **errp) { sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(d); sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); Object *root_container; char link_name[256]; gchar *child_name; Error *err = NULL; DPRINTFN("drc realize: %x", drck->get_index(drc)); /* NOTE: we do this as part of realize/unrealize due to the fact * that the guest will communicate with the DRC via RTAS calls * referencing the global DRC index. By unlinking the DRC * from DRC_CONTAINER_PATH/<drc_index> we effectively make it * inaccessible by the guest, since lookups rely on this path * existing in the composition tree */ root_container = container_get(object_get_root(), DRC_CONTAINER_PATH); snprintf(link_name, sizeof(link_name), "%x", drck->get_index(drc)); child_name = object_get_canonical_path_component(OBJECT(drc)); DPRINTFN("drc child name: %s", child_name); object_property_add_alias(root_container, link_name, drc->owner, child_name, &err); if (err) { error_report("%s", error_get_pretty(err)); error_free(err); object_unref(OBJECT(drc)); } g_free(child_name); DPRINTFN("drc realize complete"); }
static void acpi_get_cpu_info(AcpiCpuInfo *cpu) { Object *root = object_get_root(); memset(cpu->found_cpus, 0, sizeof cpu->found_cpus); object_child_foreach(root, acpi_add_cpu_info, cpu); }
PRManagerInfoList *qmp_query_pr_managers(Error **errp) { PRManagerInfoList *head = NULL; PRManagerInfoList **prev = &head; Object *container = container_get(object_get_root(), PR_MANAGER_PATH); object_child_foreach(container, query_one_pr_manager, &prev); return head; }
IOThreadInfoList *qmp_query_iothreads(Error **errp) { IOThreadInfoList *head = NULL; IOThreadInfoList **prev = &head; Object *container = container_get(object_get_root(), IOTHREADS_PATH); object_child_foreach(container, query_one_iothread, &prev); return head; }
void object_move_first(struct object* obj) { struct object * tree = NULL, * parent = NULL; /* 如果活动窗口不是顶层窗口也不是父窗口的右子节点 */ /* 将活动窗口变成父窗口的右子节点 */ if(obj == obj->parent->parent || obj == obj->parent->rchild) { return 0; } /* 找到 win_info_ptr 的父窗口 */ parent = obj->parent; while(parent == parent->parent->lchild) { parent = parent->parent; } parent = parent->parent; /* obj 有左子节点 */ /* obj 在末端 */ if(obj->lchild != NULL) { obj->lchild->parent = obj->parent; obj->parent->lchild = obj->lchild; } /* obj 没有左子节点 */ /* obj 在中间*/ else { obj->parent->lchild = NULL; } obj->lchild = parent->rchild; parent->rchild->parent =obj; obj->parent = parent; parent->rchild = obj; /* 找到这棵树根节点的父节点 */ tree = object_get_root(parent)->parent; /* 必须更新 root->parent 节点的 lchild 成员和 rchild 成员 */ /* 此时 tree == root->parent */ /* 更新最左边节点 */ tree->lchild = object_tree_l_most_node(tree->parent); /* 更新最右边节点 */ tree->rchild = object_tree_r_most_node(tree->parent); }
static void unrealize(DeviceState *d, Error **errp) { sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(d); sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); Object *root_container; char name[256]; Error *err = NULL; DPRINTFN("drc unrealize: %x", drck->get_index(drc)); root_container = container_get(object_get_root(), DRC_CONTAINER_PATH); snprintf(name, sizeof(name), "%x", drck->get_index(drc)); object_property_del(root_container, name, &err); if (err) { error_report_err(err); object_unref(OBJECT(drc)); } }
/* 总是将孩子节点加在子节点链的最左边 如果 obj 在对象树中 那么完成添加工作后一定要更新 root->parent 的 lchild 成员和 rchild 成员 这是为了保证遍历的正确 */ si_t object_attach_child(struct object * obj, struct object * child) { struct object * tree; /* parent 没有子对象 */ if(obj->rchild == NULL) { /* 作为上层对象的右子节点 */ obj->rchild = child; child->parent = obj; } else { obj = obj->rchild; /* 一直往左走 */ while(obj->lchild != NULL) { obj = obj->lchild; } /* 作为同层对象的左子节点 */ obj->lchild = child; child->parent = obj; } /* 找到这棵树根节点的父节点 */ /* 没有的话 tree == NULL */ tree = object_get_root(obj)->parent; /* obj 在对象树中 */ /* 必须更新 root->parent 节点的 lchild 成员和 rchild 成员 */ /* 此时 tree == root->parent */ if(tree != NULL) { /* 更新最左边节点 */ tree->lchild = object_tree_l_most_node(tree->parent); /* 更新最右边节点 */ tree->rchild = object_tree_r_most_node(tree->parent); } return 0; }
static si_t handle_window_activate (union message * msg) { struct object* node; si_t n = 0, i = 0; node = OBJECT_POINTER(application_widgets_for_each_increament(do_find_window, msg)); if(node == NULL) { return 0; } object_move_first(node); if(global_application.focus != NULL) { dispatch_msg_to_subchilds(node, MESSAGE_TYPE_WINDOW_DEACTIVATE); } global_application.focus = WINDOW_POINTER(node); if(WIDGET_POINTER(node)->callback != NULL) { WIDGET_POINTER(node)->callback(node, msg); } dispatch_msg_to_subchilds(node, MESSAGE_TYPE_WIDGET_REPAINT); /** * 次序提前 **/ node = object_get_root(node)->parent; n = vector_size(&global_application.window_vector); for(i = 0; i < n; ++ i) { if(vector_at(&global_application.window_vector, i) == node) { vector_move_back(&global_application.window_vector, i); break; } } return 0; }
static si_t handle_minimize_button_release(union message* msg) { struct object* tree = NULL; struct object* node = NULL; int i = 0, j = 0; struct window_info_iterator iter; /* 不能最小化或不在活动窗口的最小化按钮内释放 */ if(global_wm.active_win_info_ptr->minimize_enable != 1 || !is_point_in_area(&(msg->mouse.cursor_position), &(global_wm.active_win_info_ptr->minimize_button_area))) { return 0; } /** * send minmize msg to every client window(including subwindows) **/ tree = object_get_root(OBJECT_POINTER(global_wm.active_win_info_ptr))->parent; node = tree->lchild; while(node != NULL) { EGUI_PRINT_INFO("send minimized msg to %s", ((struct window_info*)node)->title); send_window_minimize_message(&global_wm.active_app_info_ptr->uds, msg, (si_t)node); node = object_tree_iterator_increment(tree, node); } /** * send deactive msg to client **/ send_window_deactivate_message(&global_wm.active_app_info_ptr->uds, msg, (si_t)global_wm.active_win_info_ptr); /** 通知桌面 **/ if(NULL != global_wm.desktop_app_ptr) { send_window_deactivate_message(&global_wm.desktop_app_ptr->uds, NULL, (si_t)tree->parent); } window_info_iterator_clear(&iter); /* get next active window and application */ if(all_app_traversal_decrement(&iter, _do_find_next_active_window, tree->parent)) { global_wm.active_win_info_ptr = iter.win_info_ptr; global_wm.active_app_info_ptr = iter.app_info_ptr; } else { global_wm.active_win_info_ptr = NULL; global_wm.active_app_info_ptr = NULL; return 0; } /** * 获得顶层窗口 **/ node = object_get_root(OBJECT_POINTER(global_wm.active_win_info_ptr)); /** * move next active window back **/ i = application_info_get_win_index(global_wm.active_app_info_ptr, (struct window_info*)node); j = window_manager_get_app_index(global_wm.active_app_info_ptr); vector_move_back(&(global_wm.active_app_info_ptr->window_info_vector), i); vector_move_back(&(global_wm.application_info_vector), j); /** * send active msg **/ send_window_activate_message(&global_wm.active_app_info_ptr->uds, msg, (si_t)global_wm.active_win_info_ptr); if(NULL != global_wm.desktop_app_ptr) { send_window_activate_message(&global_wm.desktop_app_ptr->uds, NULL, (si_t)node); } return 0; }
/** * 通过按下鼠标消息设置那个是活动的 * 设置活动用户应用程序和活动窗口 * * @param msg 必须是鼠标按下消息 * * @return 0 **/ static si_t mask_active_by_mouse_down(union message * msg) { struct window_info_iterator iter; window_info_iterator_clear(&iter); if(!all_app_traversal_decrement(&iter, _do_find_clicked_window, &msg->mouse.cursor_position)) { /* Clear useless pointers in tainted iter */ window_info_iterator_clear(&iter); } /* 在桌面上按下了鼠标的某个键 */ if(iter.app_info_ptr == NULL || iter.win_info_ptr == NULL) { /* 原来有活动窗口 */ if(global_wm.active_win_info_ptr != NULL) { /* 发送激死消息给原来的活动窗口 */ send_window_deactivate_message(&global_wm.active_app_info_ptr->uds, msg, (si_t)global_wm.active_win_info_ptr); /** 通知桌面 **/ if(NULL != global_wm.desktop_app_ptr) { send_window_deactivate_message(&global_wm.desktop_app_ptr->uds, NULL, (si_t)object_get_root(OBJECT_POINTER(global_wm.active_win_info_ptr))); } /* 改变活动窗口 */ global_wm.active_win_info_ptr = NULL; global_wm.active_app_info_ptr = NULL; } } /* 在窗口上按下了鼠标的某个键 */ else if(global_wm.active_win_info_ptr != iter.win_info_ptr) { /* 原来有活动窗口 */ if(global_wm.active_win_info_ptr != NULL) { /* 发送激死消息给原来的活动窗口 */ send_window_deactivate_message(&global_wm.active_app_info_ptr->uds, msg, (si_t)global_wm.active_win_info_ptr); /** 通知桌面 **/ if(NULL != global_wm.desktop_app_ptr) { send_window_deactivate_message(&global_wm.desktop_app_ptr->uds, NULL, (si_t)object_get_root(OBJECT_POINTER(global_wm.active_win_info_ptr))); } } /* 将活动窗口移动到该用户应用程序的窗口向量的尾部 */ vector_move_back(&(iter.app_info_ptr->window_info_vector), iter.win_index); /* 将活动程序移动到用户应用程序向量的尾部 */ vector_move_back(&(global_wm.application_info_vector), iter.app_index); /* 将活动窗口作为父控件的长子控件 */ object_move_first(OBJECT_POINTER(iter.win_info_ptr)); /* 改变活动窗口 */ global_wm.active_win_info_ptr = iter.win_info_ptr; global_wm.active_app_info_ptr = iter.app_info_ptr; send_window_activate_message(&global_wm.active_app_info_ptr->uds, msg, (si_t)iter.win_info_ptr); if(NULL != global_wm.desktop_app_ptr) { send_window_activate_message(&global_wm.desktop_app_ptr->uds, NULL, (si_t)iter.top_win_info_ptr); } } return 0; }
si_t object_delete(struct object* object, void(*destructor)(void*)) { if(object->parent->parent == object) { object_tree_for_each(object, destructor); } else { /* 找到这棵树根节点的父节点 */ struct object* tree = object_get_root(object)->parent; /* 是父节点的右子节点 */ if(object == object->parent->rchild) { /* object 没有左子节点 */ /* parent 的下一层对象只有 object */ if(object->lchild == NULL) { /* 清除父节点中的指针 */ object->parent->rchild = NULL; } /* object 有左子节点 */ /* parent 的下一层有多个对象 */ else { /* 处理 object 同层的对象 */ object->parent->rchild = object->lchild; object->lchild->parent = object->parent; /* 清空 object->lchild */ object->lchild = NULL; } } /* 是父节点的左子节点 */ /* 此时 parent 的下一层有多个对象 */ else if(object == object->parent->lchild) { /* object 没有左子节点 */ /* object 处于末端 */ if(object->lchild == NULL) { /* 清除父节点中的指针 */ object->parent->lchild = NULL; } /* object 有左子节点 */ /* object 处于中间 */ else { /* 处理 object 同层的对象 */ object->parent->lchild = object->lchild; object->lchild->parent = object->parent; /* 清空 object->lchild */ object->lchild = NULL; } } object_tree_for_each(object, destructor); /* 必须更新 root->parent 节点的 lchild 和 rchild */ /* 此时 tree == root->parent */ if(tree != NULL) { /* 更新最左边节点 */ tree->lchild = object_tree_l_most_node(tree->parent); /* 更新最右边节点 */ tree->rchild = object_tree_r_most_node(tree->parent); } } return 0; }
/* PC hardware initialisation */ static void pc_init1(MemoryRegion *system_memory, MemoryRegion *system_io, ram_addr_t ram_size, const char *boot_device, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model, int pci_enabled, int kvmclock_enabled) { int i; ram_addr_t below_4g_mem_size, above_4g_mem_size; PCIBus *pci_bus; ISABus *isa_bus; PCII440FXState *i440fx_state; int piix3_devfn = -1; qemu_irq *cpu_irq; qemu_irq *gsi; qemu_irq *i8259; qemu_irq *smi_irq; GSIState *gsi_state; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; BusState *idebus[MAX_IDE_BUS]; ISADevice *rtc_state; ISADevice *floppy; MemoryRegion *ram_memory; MemoryRegion *pci_memory; MemoryRegion *rom_memory; DeviceState *dev; pc_cpus_init(cpu_model); if (kvmclock_enabled) { kvmclock_create(); } if (ram_size >= 0xe0000000 ) { above_4g_mem_size = ram_size - 0xe0000000; below_4g_mem_size = 0xe0000000; } else { above_4g_mem_size = 0; below_4g_mem_size = ram_size; } if (pci_enabled) { pci_memory = g_new(MemoryRegion, 1); memory_region_init(pci_memory, "pci", INT64_MAX); rom_memory = pci_memory; } else { pci_memory = NULL; rom_memory = system_memory; } /* allocate ram and load rom/bios */ if (!xen_enabled()) { pc_memory_init(system_memory, kernel_filename, kernel_cmdline, initrd_filename, below_4g_mem_size, above_4g_mem_size, pci_enabled ? rom_memory : system_memory, &ram_memory); } gsi_state = g_malloc0(sizeof(*gsi_state)); if (kvm_irqchip_in_kernel()) { kvm_piix3_setup_irq_routing(pci_enabled); gsi = qemu_allocate_irqs(kvm_piix3_gsi_handler, gsi_state, GSI_NUM_PINS); } else { gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS); } if (pci_enabled) { pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, &isa_bus, gsi, system_memory, system_io, ram_size, below_4g_mem_size, 0x100000000ULL - below_4g_mem_size, 0x100000000ULL + above_4g_mem_size, (sizeof(target_phys_addr_t) == 4 ? 0 : ((uint64_t)1 << 62)), pci_memory, ram_memory); } else { pci_bus = NULL; i440fx_state = NULL; isa_bus = isa_bus_new(NULL, system_io); no_hpet = 1; } isa_bus_irqs(isa_bus, gsi); if (kvm_irqchip_in_kernel()) { i8259 = kvm_i8259_init(isa_bus); } else if (xen_enabled()) { i8259 = xen_interrupt_controller_init(); } else { cpu_irq = pc_allocate_cpu_irq(); i8259 = i8259_init(isa_bus, cpu_irq[0]); } for (i = 0; i < ISA_NUM_IRQS; i++) { gsi_state->i8259_irq[i] = i8259[i]; } if (pci_enabled) { ioapic_init(gsi_state); } pc_register_ferr_irq(gsi[13]); dev = pc_vga_init(isa_bus, pci_enabled ? pci_bus : NULL); if (dev) { object_property_add_child(object_get_root(), "vga", OBJECT(dev), NULL); } if (xen_enabled()) { pci_create_simple(pci_bus, -1, "xen-platform"); } /* init basic PC hardware */ pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, xen_enabled()); for(i = 0; i < nb_nics; i++) { NICInfo *nd = &nd_table[i]; if (!pci_enabled || (nd->model && strcmp(nd->model, "ne2k_isa") == 0)) pc_init_ne2k_isa(isa_bus, nd); else pci_nic_init_nofail(nd, "e1000", NULL); } ide_drive_get(hd, MAX_IDE_BUS); if (pci_enabled) { PCIDevice *dev; if (xen_enabled()) { dev = pci_piix3_xen_ide_init(pci_bus, hd, piix3_devfn + 1); } else { dev = pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1); } idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0"); idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1"); /* FIXME there's some major spaghetti here. Somehow we create the * devices on the PIIX before we actually create it. We create the * PIIX3 deep in the recess of the i440fx creation too and then lose * the DeviceState. * * For now, let's "fix" this by making judicious use of paths. This * is not generally the right way to do this. */ object_property_add_child(object_resolve_path("/i440fx/piix3", NULL), "rtc", (Object *)rtc_state, NULL); } else { for(i = 0; i < MAX_IDE_BUS; i++) { ISADevice *dev; dev = isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i], ide_irq[i], hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]); idebus[i] = qdev_get_child_bus(&dev->qdev, "ide.0"); } } audio_init(isa_bus, pci_enabled ? pci_bus : NULL); pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, floppy, idebus[0], idebus[1], rtc_state); if (pci_enabled && usb_enabled) { usb_uhci_piix3_init(pci_bus, piix3_devfn + 2); } if (pci_enabled && acpi_enabled) { i2c_bus *smbus; smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, first_cpu, 1); /* TODO: Populate SPD eeprom data. */ smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100, gsi[9], *smi_irq, kvm_enabled()); smbus_eeprom_init(smbus, 8, NULL, 0); } if (pci_enabled) { pc_pci_device_init(pci_bus); } }
/** * spapr_drc_populate_dt * * @fdt: libfdt device tree * @path: path in the DT to generate properties * @owner: parent Object/DeviceState for which to generate DRC * descriptions for * @drc_type_mask: mask of sPAPRDRConnectorType values corresponding * to the types of DRCs to generate entries for * * generate OF properties to describe DRC topology/indices to guests * * as documented in PAPR+ v2.1, 13.5.2 */ int spapr_drc_populate_dt(void *fdt, int fdt_offset, Object *owner, uint32_t drc_type_mask) { Object *root_container; ObjectProperty *prop; ObjectPropertyIterator *iter; uint32_t drc_count = 0; GArray *drc_indexes, *drc_power_domains; GString *drc_names, *drc_types; int ret; /* the first entry of each properties is a 32-bit integer encoding * the number of elements in the array. we won't know this until * we complete the iteration through all the matching DRCs, but * reserve the space now and set the offsets accordingly so we * can fill them in later. */ drc_indexes = g_array_new(false, true, sizeof(uint32_t)); drc_indexes = g_array_set_size(drc_indexes, 1); drc_power_domains = g_array_new(false, true, sizeof(uint32_t)); drc_power_domains = g_array_set_size(drc_power_domains, 1); drc_names = g_string_set_size(g_string_new(NULL), sizeof(uint32_t)); drc_types = g_string_set_size(g_string_new(NULL), sizeof(uint32_t)); /* aliases for all DRConnector objects will be rooted in QOM * composition tree at DRC_CONTAINER_PATH */ root_container = container_get(object_get_root(), DRC_CONTAINER_PATH); iter = object_property_iter_init(root_container); while ((prop = object_property_iter_next(iter))) { Object *obj; sPAPRDRConnector *drc; sPAPRDRConnectorClass *drck; uint32_t drc_index, drc_power_domain; if (!strstart(prop->type, "link<", NULL)) { continue; } obj = object_property_get_link(root_container, prop->name, NULL); drc = SPAPR_DR_CONNECTOR(obj); drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); if (owner && (drc->owner != owner)) { continue; } if ((drc->type & drc_type_mask) == 0) { continue; } drc_count++; /* ibm,drc-indexes */ drc_index = cpu_to_be32(drck->get_index(drc)); g_array_append_val(drc_indexes, drc_index); /* ibm,drc-power-domains */ drc_power_domain = cpu_to_be32(-1); g_array_append_val(drc_power_domains, drc_power_domain); /* ibm,drc-names */ drc_names = g_string_append(drc_names, drck->get_name(drc)); drc_names = g_string_insert_len(drc_names, -1, "\0", 1); /* ibm,drc-types */ drc_types = g_string_append(drc_types, spapr_drc_get_type_str(drc->type)); drc_types = g_string_insert_len(drc_types, -1, "\0", 1); } object_property_iter_free(iter); /* now write the drc count into the space we reserved at the * beginning of the arrays previously */ *(uint32_t *)drc_indexes->data = cpu_to_be32(drc_count); *(uint32_t *)drc_power_domains->data = cpu_to_be32(drc_count); *(uint32_t *)drc_names->str = cpu_to_be32(drc_count); *(uint32_t *)drc_types->str = cpu_to_be32(drc_count); ret = fdt_setprop(fdt, fdt_offset, "ibm,drc-indexes", drc_indexes->data, drc_indexes->len * sizeof(uint32_t)); if (ret) { fprintf(stderr, "Couldn't create ibm,drc-indexes property\n"); goto out; } ret = fdt_setprop(fdt, fdt_offset, "ibm,drc-power-domains", drc_power_domains->data, drc_power_domains->len * sizeof(uint32_t)); if (ret) { fprintf(stderr, "Couldn't finalize ibm,drc-power-domains property\n"); goto out; } ret = fdt_setprop(fdt, fdt_offset, "ibm,drc-names", drc_names->str, drc_names->len); if (ret) { fprintf(stderr, "Couldn't finalize ibm,drc-names property\n"); goto out; } ret = fdt_setprop(fdt, fdt_offset, "ibm,drc-types", drc_types->str, drc_types->len); if (ret) { fprintf(stderr, "Couldn't finalize ibm,drc-types property\n"); goto out; } out: g_array_free(drc_indexes, true); g_array_free(drc_power_domains, true); g_string_free(drc_names, true); g_string_free(drc_types, true); return ret; }
static Object *get_chardevs_root(void) { return container_get(object_get_root(), "/chardevs"); }
/* 如果 obj 有左子节点 那么这个左子节点并不是 obj 子对象 所以在析构以 obj 为根的树之前一定要要将 obj->lchild 成员清空 如果 obj 在对象树中 那么完成删除工作后一定要更新 root->parent 的 lchild 成员和 rchild 成员 这是为了保证遍历的正确 */ si_t object_remove(struct object * obj) { struct object * tree; /* obj 有父对象 */ if(obj->parent != NULL) { /* 找到这棵树根节点的父节点 */ /* 没有的话 tree == NULL */ tree = object_get_root(obj)->parent; /* obj 是由父节点右子节点 */ if(obj == obj->parent->rchild) { /* obj 没有左子节点 */ /* parent 的下一层对象只有 obj */ if(obj->lchild == NULL) { /* 清除父节点中的指针 */ obj->parent->rchild = NULL; } /* obj 有左子节点 */ /* parent 的下一层有多个对象 */ else { /* 处理 obj 同层的对象 */ obj->parent->rchild = obj->lchild; obj->lchild->parent = obj->parent; /* 清空 obj->lchild */ obj->lchild = NULL; } } /* obj 是由父节点左子节点 */ /* 此时 parent 的下一层有多个对象 */ else if(obj == obj->parent->lchild) { /* obj 没有左子节点 */ /* obj 处于末端 */ if(obj->lchild == NULL) { /* 清除父节点中的指针 */ obj->parent->lchild = NULL; } /* obj 有左子节点 */ /* obj 处于中间 */ else { /* 处理 obj 同层的对象 */ obj->parent->lchild = obj->lchild; obj->lchild->parent = obj->parent; /* 清空 obj->lchild */ obj->lchild = NULL; } } /* 删除 obj 以及它的所有子对象 */ object_tree_free(obj); /* obj 在对象树中 */ /* 必须更新 root->parent 节点的 lchild 成员和 rchild 成员 */ /* 此时 tree == root->parent */ if(tree != NULL) { /* 更新最左边节点 */ tree->lchild = object_tree_l_most_node(tree->parent); /* 更新最右边节点 */ tree->rchild = object_tree_r_most_node(tree->parent); } } /* 没有父对象 */ else { /* 清空 obj->lchild */ obj->lchild = NULL; /* 删除 obj 以及它的所有子对象 */ object_tree_free(obj); } return 0; }